【问题标题】:Need to implement destructor, copy constructor, assignment operator when using shared_ptr使用shared_ptr时需要实现析构函数、复制构造函数、赋值运算符
【发布时间】:2017-06-24 11:05:50
【问题描述】:

我正在开发 c++11 项目。其中我有一个shared_ptr 持有std::string 数据。

class Base {
 public:
  Base() : Base(string()) {}
  virtual ~Base() = default;
  Base(const string &str) {
    str_ = std::make_shared<string>(str);
  }
 private:
  std::shared_ptr<std::string> str_;
};

我的问题是:我应该在这里实现析构函数来释放str_、复制构造函数和赋值运算符来处理副本吗? 如果我依赖编译器提供的默认值就足够了吗? 我想允许通过Base b1("string"); 在堆栈中或通过Base *b1 = new Base("string"); 在堆中创建此类的对象

【问题讨论】:

  • 不,您不需要创建它们。
  • 为什么要使用 shared_ptr 来保存字符串?你真的希望这个对象的副本引用相同的字符串吗?如果是,为什么?
  • 您可以依赖编译器提供的默认实现,因为默认提供的简单成员复制就足够了。
  • 通常在具有虚拟 dtor 的类中,您要删除复制和移动构造函数和赋值运算符,或者至少将它们设为私有/受保护。
  • @RuLoViC 没有。如果您希望它是线程安全的,则需要保存一个指向同时包含字符串和互斥体的结构的共享指针。您还需要在访问字符串时保持互斥锁锁定。要进一步评论,我需要知道用例。您可能会受益于在 codereview.stackexchange.com/questions/tagged/c%2b%2b 上发布您的设计并解释用例。

标签: c++ c++11 destructor shared-ptr copy-constructor


【解决方案1】:

默认构造函数和赋值运算符(复制和移动)将是“正确的”。我在引号中加上“正确”的原因是我担心您打算从这个 Base 类派生类(给定虚拟析构函数和名称),并且如果您写如下内容:

Base *p1 = new Derived1("foo", "bar");
Base *p2 = new Derived1("bar", "foo");
*p1 = *p2;   // Will compile, but probably won't do what you want.

具体来说,赋值将复制p2指向的对象的Base部分,但不会复制任何Derived1部分。

我要么删除构造函数和赋值运算符,要么让它们受到保护。

class Base {
 public:
  Base() : Base(string()) {}
//Either
  Base(const Base& rhs) = delete;
  Base& operator=(const Base& rhs) = delete;
//OR
protected:
  Base(const Base&rhs) = default;
  Base& operator=(const Base& rhs) = default;
  Base(Base&&rhs) = default;
  Base& operator=(Base&& rhs) = default;
public:
//END
  virtual ~Base() = default;
  Base(const string &str) {
    str_ = std::make_shared<string>(str);
  }
 private:
  std::shared_ptr<std::string> str_;
};

【讨论】:

  • 是的,我将从它创建派生类 请详细说明,我为什么要“保护”它们或禁用它们?谢谢
  • 因为如果您不这样做,那么*p1 = *p2 将分配基类值而不是派生元素!。我已经编辑了答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
  • 2015-01-04
  • 2012-06-27
  • 1970-01-01
  • 2014-09-06
  • 2011-07-26
  • 2011-07-19
相关资源
最近更新 更多