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

C++ 在复制构造函数中调用赋值运算符,c++,copy-constructor,C++,Copy Constructor,复制构造函数的这种实现是否存在一些缺点 Foo::Foo(const Foo& i_foo) { *this = i_foo; } 正如我所记得的,在一些书中建议从赋值运算符调用复制构造函数并使用众所周知的交换技巧,但我不记得,为什么…您正在寻找第12项:复制对象的所有部分。是的,这是个坏主意。用户定义类型的所有成员变量将首先初始化,然后立即覆盖 交换技巧是这样的: Foo& operator=(Foo rhs) // note the copying { rhs.

复制构造函数的这种实现是否存在一些缺点

Foo::Foo(const Foo& i_foo)
{
   *this = i_foo;
}

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

您正在寻找第12项:复制对象的所有部分。

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

交换技巧是这样的:

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 

在构造函数中调用
操作符=()
既有潜在的缺点,也有潜在的好处

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

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

利润:
  • 代码库变得不那么复杂,更易于维护。再一次,明智地评估这一收益。如果您有一个包含两个字符串成员的结构,那么它可能不值得。另一方面,如果你有一个有50个数据成员的类(你可能不应该,但这是另一篇文章的故事),或者数据成员之间有着复杂的关系,那么只有一个init函数而不是两个或更多的init函数可能会带来很多好处

另一个副本的可能副本:相关:那是哪本书?很好的做法是调用公共代码(可能是在命名的私有函数中)来执行复制。但是要从复制构造函数中使用赋值运算符?在大多数情况下-不,“这是一个坏主意,”在我看来是一个过于宽泛的说法。说这句话,你有可能过早地进行微观优化。如果在ctor和
op=()
中都编写了分配代码,则会创建代码的副本并违反DRY。找出双重初始化所涉及的成本,将其与降低代码库复杂性所获得的好处进行比较,然后确定哪种方法是正确的。交换技巧的好处在于它自动处理自分配,并且(假设
.swap()
不抛出)具有很强的异常安全性,在这种情况下,要么赋值成功,要么保持不变,然后抛出异常。除了现在,通过按值传递rhs,技巧会做得更好。看@Kaz:你说得对
这两次我不得不承认我做的事情主要是出于旧习惯,而不是为什么它(仍然)被认为是最先进的。也许我已经老了。@JohnDibling从copyctor调用op=()并不是避免代码重复的唯一方法,我认为在所有技术中,它仍然不是一个很好的方法。