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

Lifetime of vector::push_back() elements

本文关键字:元素 周期 生命 push back vector      更新时间:2023-10-16

我想确认一下我对在std::vector上被push_back() 'ed的对象的生命周期的理解。我读到的是向量中的元素是副本。那么,下面的用法可以吗?具体来说,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;
    }
}

是的。字符串s的副本在push_back期间存储。查看文档了解详细信息。州:

void push_back ( const T& x );

在vector对象当前最后一个元素的末尾添加一个新元素。


参数x
要复制到新元素的值
T是第一个模板形参(vector容器中存储元素的类型)。

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

注意,这是不必要的低效。因为s是左值,所以push_back确实会进行复制。如果你说pv->push_back(std::string("hi")), c++ 0x编译器可以用移动来替换拷贝,因为std::string("hi")是一个右值。你甚至可以说:

pv->emplace_back("hi");

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

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

是正确的。字符串s将被复制。

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

在你的代码中,回推s将复制一个string实例,但不会复制字符"hi",所以这将相对较快。

编辑:

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