我正在学习c++,最近我学习了有关 copy-and-swap 的习惯用法(在堆栈溢出中),我对此有一些疑问。因此,假设我有以下使用 copy-and-swap 惯用法的类,例如:

class Foo {
private:
  int * foo;
  int size;

public:
  Foo(size_t size) : size(size) { foo = new int[size](); }
  ~Foo(){delete foo;}

  Foo(Foo const& other){
    size = other.size;
    foo = new int[size];
    copy(other.foo, other.foo + size, foo);
  }

  void swap(Foo& other) {
    std::swap(foo,  other.foo);
    std::swap(size, other.size);
  }

  Foo& operator=(Foo g) {
    g.swap(*this);
    return *this;
  }

  int& operator[] (const int idx) {return foo[idx];}
};

我的问题是,假设我有另一个类,其中有一个Foo对象作为数据,但没有可能需要自定义复制或赋值的指针或其他资源:
class Bar {
private:
  Foo bar;
public:
  Bar(Foo foo) : bar(foo) {};
  ~Bar(){};
  Bar(Bar const& other) : bar(other.bar) {};
  Bar& operator=(Bar other) {bar = other.bar;}
};

现在我有一系列问题:
  • 上面为Bar类实现的方法和构造函数是否安全?使用了Foo的 copy-and-swap 功能后,确保在分配或复制Bar时不会造成任何危害吗?
  • 是否必须在复制构造函数中和通过交换传递引用参数,这是强制性的?
  • 是正确的说法,当operator=的参数按值传递时,将为该参数调用复制构造函数以生成对象的临时拷贝,然后是此拷贝与*this交换吗?如果我通过operator=中的引用传递了我,那么会有一个大问题,对吗?
  • 在某些情况下,该成语在复制和分配Foo时无法提供完全的安全性吗?
  • 最佳答案



    关于copy-ctor:始终是安全的(全有或全无)。它要么完成(全部),要么抛出异常(什么都没有)。

    如果您的类(class)仅由一个成员组成(即也没有基类),则赋值运算符将与成员类(class)一样安全。如果您有一个以上的成员,则赋值运算符将不再是“全有或全无”。第二个成员的赋值运算符可能会引发异常,在这种情况下,将为对象分配“半路”。这意味着您需要在新类中再次实现 copy-and-swap 以获取“全有或全无”分配。

    但是,从某种意义上讲,您不会泄漏任何资源,它仍然是“安全的”。当然,每个成员的状态将是一致的-只是新类的状态是不一致的,因为一个成员被分配而另一个成员没有被分配。



    是的,通过引用传递是强制性的。复制构造函数是用于复制对象的构造函数,因此它不能按值接受其参数,因为这将意味着必须复制该参数。这将导致无限递归。 (将为参数调用copy-ctor,这意味着将为参数调用copy-ctor,这意味着...)。对于交换,原因是另一个原因:如果要按值传递参数,则永远不能使用交换来真正交换两个对象的内容-交换的“目标”将是最初传递的对象的拷贝,它将立即被销毁。



    恩,那就对了。但是,通过引用引用常量作为参数,构造本地拷贝,然后与本地拷贝交换也是很常见的。但是,按引用按常量的方式有一些缺点(它禁用了一些优化)。如果您没有实现 copy-and-swap ,则可能应该通过引用常量来传递。



    我不知道。当然,使用多线程总是可以使事情失败(如果未正确同步),但这应该是显而易见的。

    10-02 00:32
    查看更多