vector :: push_back()元素的生命周期

时间:2011-08-14 05:34:18

标签: c++ stl

我想确认我认为我对std :: vector上的push_back()编辑的对象的生命周期的理解。我读到的内容是矢量中的元素是副本。那么,下面的用法是否正常?具体来说,f2()中的变量s是std :: string的一个不同的实例,而不是f1()中的push_back()',因此可以安全使用吗?

void f1(std::vector<std::string>* pv) {
    std::string s = "hi";               
    pv->push_back(s);
}

void f2(void) {
    std::vector<std::string> v;
    f1(&v);
    for (size_t i = 0; i < v.size(); ++i) {
        std::string s = v.at(i);
        std::cout << s;
    }
}

4 个答案:

答案 0 :(得分:4)

是的,这是正确的。在s期间存储字符串push_back的副本。查看 doccumentation 了解详细信息。它声明:

void push_back ( const T& x );

在向量的末尾添加一个新元素,在其当前的最后一个元素之后。 此新元素的内容初始化为x的副本。

参数
x
要复制到新元素的值
T是第一个模板参数(存储在向量中的元素的类型)。

答案 1 :(得分:3)

std::string s = "hi";               
pv->push_back(s);

请注意,这是不必要的低效率。由于s是左值,push_back确实会复制。如果你改为pv->push_back(std::string("hi")),C ++ 0x编译器可以用move替换副本,因为std::string("hi")是一个右值。你甚至可以说:

pv->emplace_back("hi");

构造字符串对象。无需复制或移动。

答案 2 :(得分:1)

当上面的push_back操作时,它确实复制了字符串s。所以,这是安全的。

答案 3 :(得分:0)

是的,这是对的。字符串s将被复制。

然而,有一个有趣的事情是如何通常实现类字符串,这是值得一提的。如果从另一个字符串或const char指针创建一个新字符串,它首先不会将所有字符复制到其内部数组,而是使用指向源数据的指针。仅当您要修改字符串(或修改源字符串)时,才会创建字符数组的实际副本。因此,如果字符串实例未被修改,则它将有效地共享字符数据。

如果是你的代码,推回s将复制字符串的实例,但不会复制字符“hi”,所以这将相对较快。

编辑:

正如其他人所指出的那样,这种写时复制字符串优化现在已不再常见,所以没关系;) here有一些信息,为什么会这样呢