在复制构造函数中调用赋值运算符

sta*_*tas 29 c++ copy-constructor

复制构造函数的这种实现有一些缺点吗?

Foo::Foo(const Foo& i_foo)
{
   *this = i_foo;
}
Run Code Online (Sandbox Code Playgroud)

我记得,在某些书中建议从赋值运算符调用复制构造函数并使用众所周知的交换技巧,但我不记得了,为什么......

sbi*_*sbi 21

是的,这是一个坏主意.将首先初始化用户定义类型的所有成员变量,然后立即覆盖.

那个交换技巧是这样的:

Foo& operator=(Foo rhs) // note the copying
{
   rhs.swap(*this); //swap our internals with the copy of rhs
   return *this;
} // rhs, now containing our old internals, will be deleted 
Run Code Online (Sandbox Code Playgroud)

  • "这是一个坏主意,"IMO声明过于宽泛.通过这样说,你可能会过早地进行微观优化.如果在ctor和`op =()`中编写赋值代码,则会创建代码重复并违反DRY.弄清楚双重初始化所涉及的成本,将它们与通过降低代码库中的复杂性所获得的好处进行比较,然后确定哪种方式是正确的. (6认同)
  • 除了这些天,通过按值传递rhs可以更好地完成这个技巧.见http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ (4认同)
  • 关于交换技巧的好处是它自动处理自我赋值,并且(假设`.swap()`不抛出)是强异常安全的,因为赋值成功或者它保持不变和异常被扔了. (2认同)
  • @JohnDibling 从 copy ctor 调用 op=() 并不是避免代码重复的唯一方法,而且我认为在所有技术中,它仍然不是一个很好的方法。 (2认同)

Joh*_*ing 8

operator=()在构造函数中调用有两个潜在的缺点和潜在的好处.

缺点:

  • 无论是否指定值,构造函数都将初始化所有成员变量,然后operator=再次初始化它们.这增加了执行复杂性.您需要明智地决定何时会在代码中创建不可接受的行为.

  • 你的构造函数和operator=紧密耦合.复制对象时,还需要在实例化对象时执行的所有操作.同样,你必须聪明地确定这是否是一个问题.

收益:

  • 代码库变得不那么复杂,也更容易维护.再一次,要聪明地评估这个收益.如果你有一个包含2个字符串成员的结构,那么它可能不值得.另一方面,如果你有一个有50个数据成员的类(你可能不应该,但这是另一个帖子的故事)或者彼此之间有复杂关系的数据成员,那么只有一个可以有很多好处init函数而不是两个或更多.