性夜影院午夜看片,无码精品久久一区二区三区,婷婷成人丁香五月综合激情,校园春色 qvod,性调教室高h学校

C++的std::string的“讀時(shí)也拷貝”技術(shù)!

C++的std::string的讀時(shí)也拷貝技術(shù)!

嘿嘿,你沒有看錯(cuò),我也沒有寫錯(cuò),是讀時(shí)也拷貝技術(shù)。什么?我的錯(cuò),你之前聽說寫過時(shí)才拷貝,嗯,不錯(cuò)的確有這門技術(shù),英文是Copy On Write,簡(jiǎn)寫就是COW,非?!!?!那么我們就來看看這個(gè)’?!夹g(shù)的效果吧。

我們先編寫一段程序

#include <string>
#include <iostream>
#include <sys/time.h>
static long getcurrenttick()
{
    long tick ;
    struct timeval time_val;
    gettimeofday(&time_val , NULL);
    tick = time_val.tv_sec * 1000 + time_val.tv_usec / 1000 ;
    return tick;
}
int main( )
{
    string the_base(1024 * 1024 * 10, 'x');
    long begin =  getcurrenttick();
    for( int i = 0 ;i< 100 ;++i ) {
       string the_copy = the_base ;
    }
    fprintf(stdout,"耗時(shí)[%d] \n",getcurrenttick() - begin );
}

嗯,一個(gè)非常大的字符串,有10M字節(jié)的x,并且執(zhí)行了100此拷貝。編譯執(zhí)行它,非???,在我的虛擬機(jī)甚至不要1個(gè)毫秒。

現(xiàn)在我們來對(duì)這個(gè)string加點(diǎn)料!

int main(void) {
    string the_base(1024 * 1024 * 10, 'x');
    long begin =  getcurrenttick();
    for (int i = 0; i < 100; i++) {
        string the_copy = the_base;
        the_copy[0] = 'y';
    }
    fprintf(stdout,"耗時(shí)[%d] \n",getcurrenttick() - begin );
}

現(xiàn)在我們?cè)倬幾g并執(zhí)行這斷程序,居然需要4~5秒!哇!非常美妙的寫時(shí)才拷貝技術(shù),性能和功能的完美統(tǒng)一。

我們?cè)賮砜纯戳硗庖环N情況!

string original = "hello";
char & ref = original[0];
string clone = original;
ref = 'y';

我們生成了一個(gè)string,并保留了它首字符的引用,然后復(fù)制這個(gè)string,修改string中的首字符。因?yàn)閷懖僮髦皇侵苯拥男薷牧藘?nèi)存中的指定位置,這個(gè)string就根本不能感知到有寫發(fā)生,如果寫時(shí)才拷貝是不成熟的,那么我們將同時(shí)會(huì)修改original和clone兩個(gè)string。那豈不是災(zāi)難性的結(jié)果?幸好上述問題不會(huì)發(fā)生。clone的值肯定是沒有被修改的??磥鞢OW就是非常的牛!

以上都證明了我們的COW技術(shù)非常牛!

有太陽就有黑暗,這句說是不是有點(diǎn)耳熟?

int main(void) {
    string the_base(1024 * 1024 * 10, 'x');
    fprintf(stdout,"the_base's first char is [%c]\n",the_base[0] );
    long begin =  getcurrenttick();
    for (int i = 0; i < 100; i++) {
        string the_copy = the_base;
    }
    fprintf(stdout,"耗時(shí)[%d] \n",getcurrenttick() - begin );
}

啊,居然也是4~5秒!你可能在想,我只是做了一個(gè)讀,沒有寫嘛,這到底是怎么回事?難道還有讀時(shí)也拷貝的技術(shù)!。

不錯(cuò),為了避免了你通過[]操作符獲取string內(nèi)部指針而直接修改字符串的內(nèi)容,在你使用了the_base[0]后,這個(gè)字符串的寫時(shí)才拷貝技術(shù)就失效了。

C++標(biāo)準(zhǔn)的確就是這樣的,C++標(biāo)準(zhǔn)認(rèn)為,當(dāng)你通過迭代器或[]獲取到string的內(nèi)部地址的時(shí)候,string并不知道你將是要讀還是要寫。這是它無法確定,為此,當(dāng)你獲取到內(nèi)部引用后,為了避免不能捕獲你的寫操作,它在此時(shí)廢止了寫時(shí)才拷貝技術(shù)!

這樣看來我們?cè)谑褂肅OW的時(shí)候,一定要注意,如果你不需要對(duì)string的內(nèi)部進(jìn)行修改,那你就千萬不要使用通過[]操作符和迭代器去獲取字符串的內(nèi)部地址引用,如果你一定要這么做,那么你就必須要付出代價(jià)。當(dāng)然,string還提供了一些使迭代器和引用失效的方法。比如說push_back,等, 你在使用[]之后再使用迭代器之后,引用就有可能失效了。那么你又回到了COW的世界!比如下面的一個(gè)例子

int main( )
{
    struct timeval time_val;
    string the_base(1024 * 1024 * 10, 'x');
    long begin = 0 ;
    fprintf(stdout,"the_base's first char is [%c]\n",the_base[0] );
    the_base.push_back('y');
    begin = getcurrenttick();
    for( int i = 0 ;i< 100 ;++i ) {
        string the_copy = the_base ;
    }
    fprintf(stdout,"耗時(shí)[%d] \n",getcurrenttick() - begin );
}

一切又恢復(fù)了正常!如果對(duì)[]返回引用進(jìn)行了操作又會(huì)發(fā)生情況呢,有興趣的朋友可以試試!結(jié)果非常令人驚訝。

另外:上述例子是在Linux環(huán)境下編譯的,使用STL是GNU的STL。windows上我用的是vs2003,但是非常明顯vs2003一點(diǎn)都不支持COW。

這篇文章出自http://ridiculousfish.com/blog/archives/2009/09/17/i-didnt-order-that-so-why-is-it-on-my-bill-episode-2/ 這里,我使用了它的例子。但是我重新自己組織了內(nèi)容。

編寫這篇文章的同時(shí),我還參考了耗子的《標(biāo)準(zhǔn)C++類string的Copy-On-Write技術(shù)》一文

轉(zhuǎn)自:http://coolshell.cn/articles/1443.html

相關(guān)新聞

歷經(jīng)多年發(fā)展,已成為國(guó)內(nèi)好評(píng)如潮的Linux云計(jì)算運(yùn)維、SRE、Devops、網(wǎng)絡(luò)安全、云原生、Go、Python開發(fā)專業(yè)人才培訓(xùn)機(jī)構(gòu)!