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

问题描述 投票:0回答:4

我想确认我对已在

push_back()
上进行过
std::vector
处理的对象的生命周期的理解。我读到的内容是向量中的元素是副本。那么,下面的用法可以吗?具体来说,
f2()
中的变量 s 是否是
std::string
中的变量 s 与
push_back()
f1()
'ed 的不同实例,因此可以安全使用?

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;
    }
}
c++ stl
4个回答
5
投票
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");

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


4
投票

是的,这是正确的。在

s
期间存储字符串
push_back
的副本。检查文档了解详细信息。它指出:

void push_back ( const T& x );

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

参数

x

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


1
投票

当上面的push_back操作时,它确实复制了字符串

s
。所以,它是安全的。


0
投票

是的,这是正确的。字符串

s
将被复制。

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

对于您的代码,推回

s
将复制字符串的实例,但不会复制字符“hi”,因此这会相对较快。

编辑:

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

© www.soinside.com 2019 - 2024. All rights reserved.