C++ make_shared()在为析构函数提供已创建的对象时调用析构函数两次

C++ make_shared()在为析构函数提供已创建的对象时调用析构函数两次,c++,c++11,visual-studio-2013,visual-studio-2015,C++,C++11,Visual Studio 2013,Visual Studio 2015,使用VS 2015和v120 所以我得到了内存异常,因为当我在已经构建的对象上调用make_shared时。已经构造的对象有一个指向另一个对象的指针,该对象在第一次调用析构函数时被分配了new so。对象被销毁,然后当它再次调用它时,该对象已被销毁 我认为在这个例子中,对象将被移动,并且析构函数永远不会被调用 代码: 子对象: #include "Obj.h" Obj::Obj(int i) { cout << "const Obj " << this <

使用VS 2015和v120

所以我得到了内存异常,因为当我在已经构建的对象上调用make_shared时。已经构造的对象有一个指向另一个对象的指针,该对象在第一次调用析构函数时被分配了new so。对象被销毁,然后当它再次调用它时,该对象已被销毁

我认为在这个例子中,对象将被移动,并且析构函数永远不会被调用

代码:

子对象:

#include "Obj.h"

Obj::Obj(int i)
{
    cout << "const Obj " << this << "\n";
    m_i = i;
}
Obj::~Obj()
{
    cout << "-------------------DELETING  o " << this << "\n";
}

这是我用来说明问题的测试代码。在真实的项目中,我创建了需要包含大量信息的对象,然后将它们推送到一个向量上,该向量由多个线程共享以处理这些信息。这样,无论最后一个线程中有什么对象,都会将其删除

Erm-复制BigObj的构造函数复制内部指针Obj,然后在清理自动实例和共享指针后,会对其进行两次删除。这不好。。BigObj的复制构造函数没有做正确的事情,它应该使用它的复制构造函数实例化子对象Obj

编辑:一个干净的实现

class Obj
{
};

class BigObj
{
public:
  // Default constructor
  BigObj() : _obj(new Obj)
  { }
  // Move constructor
  BigObj(BigObj&& other) : _obj(move(other._obj)) // take ownership of the subobject
  { }
  // Move assignment
  BigObj& operator=(BigObj&& other)
  {
    _obj = move(other._obj); // take ownership of the subobject
    return *this;
  }
private:
  unique_ptr<Obj> _obj;
};
这:


这应该可以解决您的问题,但是您还应该研究深度副本和浅层副本,以了解为什么副本构造函数有问题。

m\o是什么类型的?你的BigObj复制构造函数似乎违反了三条规则……你为什么不写一个最小的、完整的例子呢?我把它添加到测试中了。我需要它吗?移除它不会改变任何事情。那我该怎么办?@unixsnob不确定你指的是什么-我做了一些编辑让你工作。我给尼姆做了一个评论,解释我希望这个对象的行为。有帮助吗?我可以添加更多信息。@unixsnob是的。make_shared不仅仅创建一个共享的_ptr,它还构造一个类型为T的对象,然后将一个共享的_ptr返回给该对象。如果您已经拥有该对象,则不应使用make_shared。抱歉,请告诉我需要更改什么。我有点困惑。我需要一个复制构造函数吗?这取决于你希望BigObj的行为,如果你想转移子对象的所有权,那么在BigObj和move instance中有一个移动构造函数,否则在BigObj的复制构造函数中,通过复制传入实例的子对象来实例化子对象,即触发对象的复制构造函数实际代码的工作方式。BigObj有各种各样的指针,它被传递给几个函数,这些函数进行分配并设置指针。然后BigObj被共享,这样它就可以被传递了。如果信息收集失败,对象将被丢弃。在我知道其中有数据之前,我不会进行共享。然后你应该支持移动语义,即你的BigObj应该只有一个移动构造函数,并删除复制构造函数。在移动中,只需使用指针即可。我也会将这些子对象保存在唯一的_ptr实例中,因为这将非常清楚您的意图。您介意编写move构造函数吗。我不太清楚你是怎么申报的。
int main(char argc, char** argv){

    BigObj oo = BigObj(10);
    shared_ptr<BigObj> shr= make_shared<BigObj>(oo);

    BigObj oo2 = BigObj(100);
    cout << "finished\n";
    system("pause");
}
const BIgObj 000000C61F4FFAD8
const Obj 000000C61F658330
called copy const
const BIgObj 000000C61F4FFB28
const Obj 000000C61F658510
finished
Press any key to continue . . .
-------------------DELETING  o 000000C61F658510
----------------DEL bigobj 000000C61F4FFB28
-------------------DELETING  o 000000C61F658330
----------------DEL bigobj 000000C61F65AFB0
-------------------DELETING  o 000000C61F658330
class Obj
{
};

class BigObj
{
public:
  // Default constructor
  BigObj() : _obj(new Obj)
  { }
  // Move constructor
  BigObj(BigObj&& other) : _obj(move(other._obj)) // take ownership of the subobject
  { }
  // Move assignment
  BigObj& operator=(BigObj&& other)
  {
    _obj = move(other._obj); // take ownership of the subobject
    return *this;
  }
private:
  unique_ptr<Obj> _obj;
};
BigObj oo = BigObj(10);
shared_ptr<BigObj> shr= make_shared<BigObj>(oo);
shared_ptr<BigObj> shr = make_shared<BigObj>(10);