Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过引用传递到STL容器的对象的生命周期_C++_Stl_Reference - Fatal编程技术网

C++ 通过引用传递到STL容器的对象的生命周期

C++ 通过引用传递到STL容器的对象的生命周期,c++,stl,reference,C++,Stl,Reference,我是一名经验丰富的程序员,但对STL还是比较陌生的,刚刚遇到这个问题: 据我所知,STL容器并不是为了复制它们所包含的对象,也不是为了影响它们的生命周期,但在实验上我看到了不同的结果 特别是,字符串类意味着在销毁时将其底层存储的第一个字符归零,如果它们在超出范围之前存储在容器中,则仍然可以访问它们。例如,考虑下面的例子: 使用名称空间std queue<string> strQueue; const char *genStr(int i) { ostringstream o

我是一名经验丰富的程序员,但对STL还是比较陌生的,刚刚遇到这个问题:

据我所知,STL容器并不是为了复制它们所包含的对象,也不是为了影响它们的生命周期,但在实验上我看到了不同的结果

特别是,字符串类意味着在销毁时将其底层存储的第一个字符归零,如果它们在超出范围之前存储在容器中,则仍然可以访问它们。例如,考虑下面的例子:

使用名称空间std

queue<string> strQueue;

const char *genStr(int i)
{
    ostringstream os;
    os << "The number i is " << i;
    strQueue.push(os.str());
    return strQueue.back().data();
}

void useStr()
{
    while(!strQueue.empty())
    {
        cout << strQueue.front() << endl;
        strQueue.pop();
    }
}

int main(int argc, char **argv)
{
    for(int i = 0; i < 40; i++)
    {
        printf("Retval is: %s\n", genStr(i));
    }
    useStr();

    return 0;
}
队列strQueue;
常量字符*genStr(int i)
{
ostringstream os;

os进入容器的是对象的副本,而不是实际对象。类似地,返回的也是副本。只要容器在范围内,您就可以访问这些对象

据我所知,STL容器 不是要复制 它们包含

好的,我们就到此为止。STL容器经常复制它们的内容。它们在插入时复制,在容器自动或显式调整大小时复制,在复制容器本身时复制。大量复制

我不确定你是从哪里想到STL容器不会复制它们的内容的。我能想到的唯一一件事是,如果你在STL容器中插入一个指针,它会复制指针本身,但不会复制指向数据的指针

此外,您的代码中没有任何引用,因此我对这个问题的标题所指的内容感到困惑。

所有的“STL”(我讨厌这个术语)集合存储传递给它们的对象的副本,因此集合中对象的生存期完全独立于原始对象。在正常情况下,集合中对象的副本将保持有效,直到您将其从集合中删除或销毁该集合

STL容器并不打算复制它们包含的对象

STL就是制作副本。它会在插入对象时制作副本,有时也会在底层存储调整大小时制作副本。如果要复制的对象在函数超出范围时失效,则可能会导致代码中断(例如,如果添加指向局部变量的指针,而不是复制局部变量)

在您的情况下,您不是在复制对字符串的引用,而是在复制字符串。这样,复制的字符串就存在于strQueue的作用域中,因此您看到的行为是完全有效和可靠的

下面是另一个需要澄清的误解:

特别是字符串类,这意味着在销毁时将其底层存储的第一个字符归零


C++不倾向于做这种事情,这是隐藏的成本,C++讨厌隐藏的成本:字符串析构函数不会触碰内存,因为一旦析构函数退出,对象就不再存在。访问它是未定义的行为,因此C++实现将在定义良好的代码中执行最快和最少的浪费。< / P>出于好奇,为什么您讨厌“STL”这个词。佩德罗:我没有讨厌它,但它是一个坏名字。单词标准、模板和库没有给你任何关于图书馆有用或相关的指示,使它看起来像模板是一些专门的技术,而不是你应该在你的C++应用程序中使用的东西。@佩德罗:因为不同的人意味着SUC。不同的东西,它往往导致许多误解。甚至“STL”这个词的确切含义也不尽相同。有些人指的是“标准库”,另一些是“标准模板库”,等等。即使如此,如果你指的是标准模板库,你是指15年前提交给委员会的库,该库中被接受为标准的部分,还是当前以该名称命名的库?如果你指的是标准库,哪些部分?根据Stepanov,“STL”指的是“标准模板库”所以说STL是“标准图书馆”的人约翰:尽管我对亚历山大·斯捷潘诺夫的评价很高,但我认为他还不能对某一特定的TLA做出唯一的解释。更糟糕的是,即使他是,我们至少还有三种不同的解释可供使用。我想补充一点,不要返回常量字符*。使用std::string和STD::这是他们的目的。我觉得你正处于从C转换到C++的中间。字符串类不应该做任何将其首字符归零的事情。这是C-ISM。在C++中,安全性远远领先于此。谢谢你的建议。我一般使用STD::String和STD::CUT。(正如您在useStr中看到的),printf和返回const char*只是一次惊慌失措的尝试,目的是向自己证明底层数据仍然很好,我可以依赖它。+1是最佳答案,但有一点是:“对象超出范围”不再是对象,只是原始内存…@hjhill:哪个先发生-花括号,还是析构函数?如果一棵树倒在森林里…我会修正措辞,这样就不会有歧义了tho:)你得到的不一定是副本,除非你自己复制。

int&I=vec.front();//引用第一项
谢谢-我得到的印象是STL容器通过引用存储,而不是复制数据,因为所有的存储方法都采用引用。回想起来,这是一个很糟糕的假设,但为我辩护,已经很晚了,呵呵。至于引用的事情,我假设当我调用“strQueue.push_back(os.str().data()”,r隐式地传递了对队列的引用,因为push_back只接受引用,所以我仍然相信这是正确的