我刚刚std::vector在添加新元素时偶然发现了一个问题.
当您尝试向其添加更多元素时,它似乎需要分配更多空间,它通过复制来实现 最后一个元素 它目前拥有的所有元素.这似乎假设向量中的任何元素都是完全有效的,因此副本将始终成功.
在我们的例子中,这不一定是真的.目前我们可能在向量中有一些遗留元素,因为我们选择不删除它们,它们是有效对象,但它们的数据不保证有效行为.对象有防护,但我从未考虑过向复制构造函数添加防护,因为我认为我们永远不会复制无效对象(向量强制):
CopiedClass::CopiedClass(const CopiedClass& other)
: member(other.member)
{
member->DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
碰巧当我们完成原始对象并将其留在向量中时,"成员"被置为空,所以当std :: vector尝试复制它时,它会崩溃.
是否可以防止std::vector复制该元素?或者我们是否必须防止可能的无效对象被复制?理想情况下,我们想继续假设只创建了有效的对象,但这似乎意味着我们立即将它们从向量中清除,而不是等待并在稍后阶段进行.
这实际上是你CopiedClass需要修复的设计缺陷.
std::vector 表现如预期和记录.
从你展示的小代码
member->DoSomething();
Run Code Online (Sandbox Code Playgroud)
这表明你将采用指针的浅表副本.
在我们的例子中,这不一定是真的.目前我们可能在向量中有一些遗留元素,因为我们选择不删除它们,它们是有效对象,但它们的数据不保证有效行为.
碰巧当我们完成原始对象并将其留在向量中时,"成员"被置为空,所以当std :: vector尝试复制它时,它会崩溃.
由于你的复制构造函数没有正确处理这种情况,因为遵循三条规则你的设计CopiedClass是错误的.
您应该关心创建您的深层副本member,还是使用智能指针(或纯实例成员),而不是原始指针.
智能指针应该正确处理这些成员的管理.
同样对于上面的代码片段,您应该nullpointer在盲目解除引用和调用之前进行测试DoSomething().
是否可以防止
std::vector复制该元素?
至于你问C++ 11这是可能的,但需要你永远不会改变向量的尺寸,并提供移动构造函数和赋值操作符的CopiedClass.
否则,std::vector 明确要求可复制类型(至少对于某些操作):
T必须满足CopyAssignable和CopyConstructible的要求.
您有责任正确满足这些要求.
...它通过复制当前持有的最后一个元素来实现.
另请注意:在需要调整矢量大小的情况下,将复制所有现有元素,而不仅仅是您前提的最后一个元素.