Pointers 向量<;列表<;T>&燃气轮机;保证元素地址保持不变?

Pointers 向量<;列表<;T>&燃气轮机;保证元素地址保持不变?,pointers,c++11,vector,stl,Pointers,C++11,Vector,Stl,我们都知道,vector中元素的地址可能会随着附加更多元素而改变(由于调整了大小),而列表中的元素保持在相同的地址 问题是,向量如何?比如说, vector<list<T>> container; // Insert some elements to container... T* ptr = &(container[0].back()); // Insert more elements to container... 向量容器; //在容器中插入一些元素。。。

我们都知道,
vector
中元素的地址可能会随着附加更多元素而改变(由于调整了大小),而
列表中的元素保持在相同的地址

问题是,向量如何?比如说,

vector<list<T>> container;
// Insert some elements to container...
T* ptr = &(container[0].back());
// Insert more elements to container...
向量容器;
//在容器中插入一些元素。。。
T*ptr=&(容器[0].back());
//将更多元素插入容器。。。
我们可以假定
ptr
保持有效吗


天真地说,我认为应该这样做,因为当向量调整大小时,它应该调用
list
的move构造函数,该构造函数不应该复制/移动单个元素。但是,我不知道该标准是否能保证这一点。

您可能应该将其设置为
向量
,而不是
向量
。使用
向量
,您可以确定所包含的指针不会更改(并且不会对内部列表进行任何重载复制),因为它们是向量的值,并且向量的值不会被扩展逻辑更改。这比依靠复制内部列表只移动head元素而不重新分配任何剩余节点要安全得多(这也更容易理解)。用另一种方法来做是很难理解的,这只是玩火。

对不起,不是。
std::list
的移动构造函数不是
noexcept
<代码>标准::向量
在进行大小调整时使用
std::move_if_noexcept
,这将是包含的
std::列表
s的副本。将分配和复制所有列表节点。它们的地址将不稳定。

您选择原始指针而不是智能指针的具体原因是什么?@hvd这是一个很好的观点。智能指针通常是更好的方法(取决于所讨论的所有权类型)。我只是想说明指针VS值,这就是为什么我没有在我的答案中选择一个特定的智能指针类。嗯,就实用性而言,你可能是正确的,但是我觉得如果我需要添加一个间接的级别来安全地运行,除非有技术上的原因,否则它违背C++的“精神”。另外,
vector
甚至
vector
也不是没有陷阱的:这意味着扩展向量时,新条目将以空指针开始,因此您必须始终记住实例化列表对象,与<代码>向量< /代码>不同,编译器为我保证一个新的列表对象。C++ 11需要<代码> vector <代码>来移动它的元素,而不是复制它们,并且还要求移动<代码>列表< /C> >不移动它的元素。这意味着
列表
元素不会因向
向量
添加更多项而移动。在这里使用指针是不必要的。你错了<代码>矢量在进行大小调整时需要使用
move\u if\u noexcept
<代码>列表的移动构造函数不是
noexcept
列表将被复制,而不是移动。列表中的元素应该是安全的,因为它应该移动。我说应该,因为我昨天在VC++中发现了一个bug,移动在一个不应该的地方失败。我会说测试来确定。这很容易。存储一个指针。然后继续添加到向量以强制重新定位。比较
.data()
指针。当向量移动时,将指针地址与同一元素进行比较。有一些恼人的标准缺陷,与您的情况不完全相关。例如,谢谢,KerrekSB,根据DYP在链接中的回答,似乎C++标准有一个命名为“YES”的建议。所以我想目前的(C++11)标准还不能完全保证它。@jick它还不能回答你的问题:它还要求
vector
不要复制它的任何元素。如果它确实在重新分配时复制元素,则对
list
的move构造函数的任何保证都不适用,因为将调用
list
的copy构造函数
vector
不应该复制它的元素,但我不知道标准是否真的说没有。(至少我找不到了。)谢谢你的回答!嗯,我用g++(4.7.2)和clang++(3.5.0)进行了实验,没有移动/复制元素(T类型)。因此,我猜标准不需要
vector
来复制列表。在任何情况下,
std::list
的move构造函数不是
noexcept
,是否存在技术原因,或者更可能是标准委员会的监督?MS对
std::list
的实现使用动态哨兵节点(至少在调试中?)这意味着他们的移动构造器实际上抛出了异常。委员会上就是否添加
noexcept
进行了一些辩论,其中标准不要求它是一致性扩展。这是一场激烈的自行车辩论,我承认我不记得它朝哪个方向发展。如果添加
noexcept
不是一致性扩展,那么libstdc++实际上是不一致的。可能需要复制列表。