C++ vector::push_back()元素的生存期

C++ vector::push_back()元素的生存期,c++,stl,C++,Stl,我想确认我对已在std::vector上推送的对象的生存期的理解。我读到的是向量中的元素是副本。那么,下面的用法可以吗?具体来说,f2()中的变量s是否与f1()中的push_back()中的变量s不同,因此使用起来安全 void f1(std::vector<std::string>* pv) { std::string s = "hi"; pv->push_back(s); } void f2(void) { std:

我想确认我对已在
std::vector
上推送的对象的生存期的理解。我读到的是向量中的元素是副本。那么,下面的用法可以吗?具体来说,
f2()
中的变量s是否与
f1()
中的
push_back()
中的变量s不同,因此使用起来安全

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;
    }
}
void f1(标准::向量*pv){
std::string s=“hi”;
pv->推回;
}
空f2(空){
std::向量v;
f1&v;
对于(大小i=0;istd::cout是的,这是正确的。在
推回
过程中会存储字符串
s
的副本。有关详细信息,请检查。它说明:

void push_back ( const T& x );
在向量的最后一个元素之后,在向量的末尾添加一个新元素。此新元素的内容初始化为x的副本。

参数
x

要复制到新元素的值。

T
是第一个模板参数(存储在向量中的元素类型)。

在上面的推回操作中,它确实复制了字符串
s
。因此,它是安全的。

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

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

对于您的代码,向后推
s
将复制字符串实例,但不会复制字符“hi”,因此这将相对较快

编辑:

正如其他人所指出的,这种写时复制字符串优化现在已经不常见了,所以不要担心;) 这是为什么会出现这种情况的一些信息

std::string s = "hi";               
pv->push_back(s);
请注意,这是不必要的低效。因为
s
是一个左值,
push_-back
确实会生成一个副本。如果你说
pv->push_-back(std::string(“hi”)
,C++0x编译器可以用a替换副本,因为
std::string(“hi”)
是一个右值。你甚至可以说:

pv->emplace_back("hi");

在适当的位置构造字符串对象。无需复制或移动。

是的,代码是正确的。矢量是安全的,因为矢量中的字符串是另一个对象,而不是您推入的对象。是的。但您到底为什么要使用原始指针?这更令人担忧。我认为您关心的是生存期,而不是范围。名称的范围是regi一个对象的生命周期是(在程序执行期间)的时间跨度“Charles Bailey:你不愿意通过引用来传递<代码>向量<代码>,减少无效指针、零数等的风险吗?好吧。我知道了。参考文献是指针的首选。自从80和旧习惯都很难用以来,我一直使用C。我只在真实C++中工作。老实说,我一直认为REF。引入引用只是为了允许我们键入一个字符“.”来访问一个成员而不是两个“->”。但是现在Charles指出了这一点(双关语的意思),我想我可以看到引用用法如何保护我不受空指针和无效指针的影响。最后,使用它们的真正原因是!(是的,Keith,我指的是“终生”)不是范围,谢谢。我编辑了这个问题以反映这一点。)C++03不保证写时复制,并且禁止实现
std::string
basic_string
,真的)C++ C++ C++语言。不保证,也不是最小的公共点。- 1:不保证,不常见,C++禁止,如果你喜欢线程(C++被禁止),这是个可怕的想法。总之,错误。不知道它在C++ 0x中是被禁止的,但是我记得我在一本书《C++标准库》中读过很多年。Nicolai M. Josuttis或者Bjarne Stroustroup的C++语言,你能告诉我为什么它被禁止在C++ 0x中吗?这似乎是一个合理的想法……而且我从来没有写过它是有保证的,我只写过它通常是这样实现的,我错了,但它过去在过去和唯一开始时都很常见。e string类的设计允许这种优化,gcc的(libstdc++)string类至少在2009年左右才开始这样做,所以我想说“一点也不常见”acurrateI不是真的同意向量的行为,但是既然
push_-back
的参数是一个引用,那么参数是如何被复制的呢?
push_-back
是否真的通过引用接收它的参数,并且
push_-back
的实现实现了复制?@ybakos:是的,
push_-back
本身就生成了c奥皮。