【问题标题】:vector::push_back on an object without a copy-constructor -- are pointer values lost?vector::push_back 在没有复制构造函数的对象上——指针值是否丢失?
【发布时间】:2013-03-11 21:42:39
【问题描述】:

我有一个类,Agent,它的成员属性指针指向另一个类的对象,Form:

代理.h

...//snip includes
class Agent{
private:
  Form* mvForm_ptr;
  ...
public:
  Agent();
  ~Agent();
  ...//snip additional functionality, but no copy-constructor
};

代理.cpp

#include "Agent.h"
Agent::Agent(){
  mvForm_ptr = new Form();
}
Agent::~Agent(){
  delete mvForm_ptr;
}
...

如您所见,我没有明确的 Agent 复制构造函数。后来我使用Agent如下:

Agent player;
std::vector<Agent> agentsVector;
agentsVector.push_back(player);

这似乎是 SIGSEGV 崩溃的原因,其错误报告声称 ~Agent 正在引发 EXC_BAD_ACCESS 异常。阅读 vector::push_back here 似乎 push_back 试图复制传入的值。由于我在代理类中没有复制构造函数,所以在隐式复制尝试时表单指针会发生什么情况?如果指向的值在编译器生成的隐式复制构造函数中丢失,添加显式复制构造函数会解决错误的访问异常吗?上面的 Agent 类的复制构造函数应该如何实现?这是Rule of Three所描述的前提的一个例子吗?

【问题讨论】:

标签: c++ memory-management vector stl


【解决方案1】:

在隐式复制尝试时表单指针会发生什么?

发生的情况是指针数据成员被复制,这意味着原始数据成员和副本都指向同一个对象,这反过来意味着它们都将在生命结束时尝试删除它。这些删除中只有一个可以成功。另一个导致未定义的行为

在 C++11 中,您可以通过持有 std::unique_ptr&lt;Form&gt; 而不是原始指针来解决此问题。在 C++03 中,遵循rule of three

【讨论】:

  • 我的错我搞砸了。抱歉打扰了。
【解决方案2】:

由于您没有提供复制或赋值运算符,编译器将为您生成一个,并且将复制指针但不会复制表单。每次销毁代理时,您的指针都会被释放,并且您将多次释放相同的内存。

一个简单的解决方法是使用 shared_ptr 确保只有在没有更多代理时才删除表单。

【讨论】:

  • 备注:“简单修复”将使所有复制的Agents 使用相同的Form,这很可能会导致不需要的行为(除非 OP 确实想要这样做)。
  • 我认为 unique_ptr 是更好的选择,对吧?然后再次使用向量操作制作的副本,结果可能是相同的。但是您仍然是正确的,而我的方法在这里是错误的。他可能应该防止复制并实现移动语义。
猜你喜欢
  • 2012-03-15
  • 2011-02-09
  • 1970-01-01
  • 2013-05-06
  • 2011-01-17
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多