代码之家  ›  专栏  ›  技术社区  ›  Michael F

GNU STL string:这里涉及写时拷贝吗?

  •  14
  • Michael F  · 技术社区  · 14 年前

    (免责声明:我不知道C++标准会对这个说什么…我知道,我很可怕)

    #include <string>
    using std::string;
    int main(void) {
        string basestr(1024 * 1024 * 10, 'A');
        for (int i = 0; i < 100; i++) {
            string a_copy = basestr;
        }
    }
    

    在循环体中添加写操作时 a_copy[1] = 'B'; ,一个实际的拷贝显然发生了,程序在0.3秒内运行,而不是几毫秒。100个字使它慢了大约100倍。

    #include <string>
    using std::string;
    int main(void) {
        string basestr(1024 * 1024 * 10, 'A');
        for (int i = 0; i < 100; i++) {
            string a_copy = basestr;
            a_copy[99]; // this also ran in 0.3s!
        }
    }
    

    在沉醉于我的发现一段时间后,我发现从基本字符串中读取(使用operator[])也需要0.3秒来完成整个玩具程序..对此我不是百分之百满意。STL字符串是真的在读时复制,还是允许在写时复制?我认为运算符[]对保留它返回的引用并稍后写入它的人有一些保护措施;这真的是这样吗?如果没有,到底发生了什么?如果有人可以指向C++标准中的相关部分,那也将是值得赞赏的。

    作为参考,我用 g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3 ,以及GNU STL。

    3 回复  |  直到 14 年前
        1
  •  14
  •   kennytm    14 年前

    C++没有区分 operator[] 用于阅读和写作,但仅限于 运算符[] a_copy 是可变的,可变的 运算符[] 将被选中,这将强制复制,因为该运算符返回(可变)引用。

    抄本 给一个 const string 强迫 const 版本 运算符[] 它不会复制内部缓冲区。

    char f = static_cast<const string>(a_copy)[99];
    
        2
  •  13
  •   CB Bailey    14 年前

    C++标准不禁止或强制复制或写入任何其他实现细节。 std::string

    请注意 operator[] const string实际上是一个“write”操作,因为它返回一个引用,该引用可用于在任何时候修改字符串,直到下一个对字符串进行变异的操作。这种修改不应影响任何副本。

    你试过分析其中一个吗?

    const string a_copy = basestr;
    a_copy[99];
    

    或者

    string a_copy = basestr;
    const std::string& a_copy_ref = a_copy;
    a_copy_ref[99];
    
        3
  •  2
  •   Benjamin Lindley    14 年前

    请尝试以下代码:

    #include <iostream>
    #include <iomanip>
    #include <string>
    
    using namespace std;
    
    template<typename T>
    void dump(std::ostream & ostr, const T & val)
    {
        const unsigned char * cp = reinterpret_cast<const unsigned char *>(&val);
        for(int i=0; i<sizeof(T); i++)
            ostr
                << setw(2) << setfill('0') << hex << (int)cp[i] << ' ';
        ostr << endl;
    }
    
    int main(void) {
        string a = "hello world";
        string b = a;
        dump(cout,a);
        dump(cout,b);
    
        char c = b[0];
    
        dump(cout,a);
        dump(cout,b);
    }
    

    3c 10 51 00
    3c 10 51 00
    3c 10 51 00
    5c 10 51 00
    

    这似乎表明是的,在这种情况下,它们是按读复制的。

    推荐文章