c++ - 安全赋值和复制交换习语

标签 c++ class copy-constructor rule-of-three copy-and-swap

<分区>

我正在学习 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;}
};

现在我有一系列的问题:

  1. 上面为 Bar 类实现的方法和构造函数是否安全?对 Foo 使用 copy-and-swap 后,我可以确保在分配或复制 Bar 时不会造成任何伤害吗?

  2. 在复制构造函数和交换中通过引用传递参数是强制性的吗?

  3. operator=的实参传值时,为该实参调用复制构造函数生成对象的临时拷贝,这样说对吗?这个拷贝是然后与 *this 交换的吗?如果我在 operator= 中通过引用传递,我会有一个大问题,对吗?

  4. 在复制和分配 Foo 时是否存在此习语无法提供完全安全的情况?

最佳答案

您应该尽可能地在初始化列表中初始化您的类的成员。这也将解决我在评论中告诉您的错误。考虑到这一点,您的代码将变为:

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

public:
  Foo(size_t size) : size(size), foo(new int[size]) {}
  ~Foo(){delete[] foo;} // note operator delete[], not delete

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

  Foo& swap(Foo& other) { 
    std::swap(foo,  other.foo);  
    std::swap(size, other.size); 
    return *this;
  }

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

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

class Bar {
private:
  Foo bar;
public:
  Bar(Foo foo) : bar(foo) {};
  ~Bar(){};
  Bar(Bar const& other) : bar(other.bar) { }
  Bar& swap(Bar &other) { bar.swap(other.bar); return *this; }
  Bar& operator=(Bar other) { return swap(other); }
}

自始至终使用相同的成语

注意

正如在对该问题的评论中提到的,Bar 的自定义复制构造函数等是不必要的,但我们假设 Bar 也有其他东西:- )

第二个问题

需要通过引用传递给 swap,因为两个实例都已更改。

需要通过对复制构造函数的引用传递,因为如果通过值传递,则需要调用复制构造函数

第三个问题

是的

第四题

不,但这并不总是最有效的做事方式

关于c++ - 安全赋值和复制交换习语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5905575/

相关文章:

c++ - 为什么可以使析构函数成为纯虚函数

c++ - 是否可以为 Qt 中的每种语言编译单独的应用程序?

c++ - 按段比较 64 位整数

c++ - 使用类的属性制作二维数组,更改值时遇到问题

java - 使用流程构建器来启动类(class)?

c++ - 对象创建顺序,cpp

c++ - 模板化复制构造函数因特定模板化类型而失败

c++ - 如何扩展编译器生成的复制构造函数

c++ - 对以下异步行为感到困惑

java - 使用 JAR 文件对性能造成影响