C++ 智能指针(unique_ptr)代替类成员的原始指针

C++ 智能指针(unique_ptr)代替类成员的原始指针,c++,pointers,c++11,memory-leaks,unique-ptr,C++,Pointers,C++11,Memory Leaks,Unique Ptr,给定类层次结构: class A { private: string * p_str; public: A() : p_str(new string()) { } virtual ~A() { delete p_str; } }; class B : public A { public: B() { } virtual ~B() override { } virtual void Test() { cout <<

给定类层次结构:

class A {

private:
  string * p_str;

public:
  A() : p_str(new string())
  {
  }

  virtual ~A() {
    delete p_str;
  }
};

class B : public A {
public:
  B() {
  }

  virtual ~B() override {
  }

  virtual void Test() {
    cout << "B::Test()" << endl;
  }
};

int main(int, char**)
{
  B b;

  b.Test();

    return 0;
}

??若任何派生类的构造函数抛出异常,则在任何代码变体中都会发生内存泄漏

UPD我尝试了以下代码:

包括
因此,结果是当声明成员的同一类的构造函数中发生异常时,
unique\ptr
会自动删除。

对于原始指针,您可以进行双重删除,因为您没有手动实现的复制c-tor和赋值运算符

A a;
A b = a; // b.p_str store the same address, that a.p_str
A a;
A b = a; // cannot do this, since `unique_ptr` has no copy constructor.
A b = std::move(a); // all is okay, now `b` stores `unique_ptr` with data and `a` stores `nullptr`
使用
unique\u ptr
时,您不能复制/分配对象,但可以移动它,而无需编写移动c-tor/移动分配运算符

A a;
A b = a; // b.p_str store the same address, that a.p_str
A a;
A b = a; // cannot do this, since `unique_ptr` has no copy constructor.
A b = std::move(a); // all is okay, now `b` stores `unique_ptr` with data and `a` stores `nullptr`

但实际上,我不知道为什么要将指针存储在这里,而不仅仅是
std::string类型的对象,这是您示例中的最佳解决方案。

对于原始指针,您可以进行双重删除,因为您没有手动实现的复制c-tor和赋值运算符

A a;
A b = a; // b.p_str store the same address, that a.p_str
A a;
A b = a; // cannot do this, since `unique_ptr` has no copy constructor.
A b = std::move(a); // all is okay, now `b` stores `unique_ptr` with data and `a` stores `nullptr`
使用
unique\u ptr
时,您不能复制/分配对象,但可以移动它,而无需编写移动c-tor/移动分配运算符

A a;
A b = a; // b.p_str store the same address, that a.p_str
A a;
A b = a; // cannot do this, since `unique_ptr` has no copy constructor.
A b = std::move(a); // all is okay, now `b` stores `unique_ptr` with data and `a` stores `nullptr`

但实际上,我不知道为什么要将指针存储在这里,而不仅仅是
std::string类型的对象,这是您示例中的最佳解决方案。

除了ForEveR的回复之外,使用
唯一的\u ptr
告诉读者只有一个对象引用(在本例中,拥有)该字符串。只要有一个简单的指针,阅读代码的人就不知道还有多少其他对象、局部对象或其他对象(单例对象?全局对象?)访问和/或修改该字符串。

除了ForEveR的回复之外,还可以使用
unique\u ptr
告诉读者只有一个对象引用(在本例中是拥有)该字符串。只要有一个简单的指针,阅读代码的人就不知道有多少其他对象、局部变量或其他(单例?全局变量?)访问和/或修改该字符串。

string
就是一个例子
string
就是一个例子“如果任何派生类的构造函数引发异常,则任何代码变体中都会发生内存泄漏。”你确定吗?在我看来是这样的。因为它是在构造函数中引发异常的子对象,所以在引发异常时将调用基对象的析构函数。@jaggedSpire sorry for”,但若在定义成员的类的构造函数中发生异常,则将出现内存泄漏:这是正确的,但不是您最初断言的。记住要小心你的措辞——当涉及到异常时,你抛出的异常有时会产生很大的不同。由于您已修复语句,因此它不会说如果继承器类抛出异常,将出现内存泄漏,因此我愿意删除我的原始注释。@jaggedSpire,请不要!让所有的讨论都留在这里,以便将来的读者理解“如果任何派生类的构造函数抛出异常,那么任何代码变体都会发生内存泄漏。”您确定吗?在我看来是这样的。由于它是在构造函数中引发异常的子对象,因此在引发异常时将调用基对象的析构函数。@jaggedSpire抱歉“of any derived”,但如果在定义成员的类的构造函数中发生异常,则会出现内存泄漏:这是正确的,但不是您最初断言的。记住要小心你的措辞——当涉及到异常时,你抛出的异常有时会产生很大的不同。由于您已修复语句,因此它不会说如果继承器类抛出异常,将出现内存泄漏,因此我愿意删除我的原始注释。@jaggedSpire,请不要!让所有的讨论留在这里,以便将来读者理解