3

假设我有一个正确实现了复制构造函数和重载 = 运算符的 c++ 类。通过正确实施,我的意思是他们正在工作并执行深层复制:

Class1::Class1(const Class1 &class1)
{
  // Perform copy
}
Class1& Class1::operator=(const Class1 *class1)
{
  // perform copy
  return *this;
}

现在假设我也有这个构造函数:

Class1::Class1(Class1 *class1)
{
   *this = *class1;
}

我的问题是上述构造函数是否可以接受?这是我继承和维护的代码。

4

4 回答 4

7

我会说“不”,原因如下:

  • 传统的复制构造函数接受其参数作为 const 引用,而不是指针。
  • 即使您要接受一个指针作为参数,它实际上也应该const Class1*表示该参数不会被修改。
  • 此复制构造函数效率低下(或不起作用!),因为 的所有成员Class1都是默认初始化的,然后使用复制operator=
  • operator=有同样的问题;它应该接受引用,而不是指针。

“重用”复制构造函数的传统方法operator=复制和交换习语。我建议以这种方式实施课程。

于 2010-04-30T16:45:36.007 回答
2

就个人而言,我认为这不是一个好习惯。

对于构造函数,很难想到从指向对象的指针到对象本身的隐式转换会有用的地方。

没有理由将指针指向非常量,并且如果您有指向该类的可用指针,则不难取消引用它,因此清楚地说明您想要使用复制构造函数复制对象的意图。

同样,对于非标准赋值运算符,为什么在调用站点正确取消引用时允许从指针赋值更清晰、更惯用?

于 2010-04-30T16:43:52.997 回答
2

我相信一个比到目前为止讨论的更重要的问题是您的非标准赋值运算符不会阻止编译器生成标准赋值运算符。由于您已经决定需要创建一个赋值运算符(因为您创建了复制构造函数,所以这是很好的选择),默认值几乎肯定是不够的。因此,这个类的用户在几乎任何人都认为非常基本和标准的对象使用过程中可能会成为这个问题的牺牲品。

于 2010-04-30T16:57:20.553 回答
1

对象和指向对象的指针是两个非常不同的东西。通常,当您传递对象时,您希望它们将被复制(尽管理想情况下,函数会在可能的情况下使用 const refs 以减少/消除不必要的副本)。当您传递指针时,您不希望发生任何复制。您正在传递一个指向特定对象的指针,并且根据代码,您处理该特定对象而不是它的副本可能真的很重要。

赋值运算符和带有指向该类型的指针的构造函数——尤其是可用于隐式转换的构造函数——确实会使事情变得混乱,并且很有可能创建意外的副本,这不仅可能是性能问题,而且可能导致错误。

我想不出任何充分的理由为什么您想要在指向类型的指针和类型本身之间进行隐式转换 - 甚至是显式转换。这样做的内置方法是取消引用对象。我想可能有一些特定的情况,我想不出这种事情在哪里可能是必要的或一个好主意,但我真的怀疑。当然,我强烈建议您不要这样做,除非您有特定且充分的理由这样做。

于 2010-04-30T16:53:45.703 回答