这个构造函数是否符合惯用做法?

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;
}

我的问题是上述构造函数是否符合惯例?这是我继承和维护的代码。

在我的代码中,我打算使用类的复制构造函数,而不是所讨论的构造函数。供您参考。 - Robb
4个回答

7
我认为不应该使用指针作为参数,原因如下:
  • 传统的拷贝构造函数接受其参数为const引用,而不是指针。
  • 即使您接受指针作为参数,它也应该是const Class1*类型的,表示参数不会被修改。
  • 这个拷贝构造函数效率低下(或者根本无法工作!),因为Class1的所有成员都是默认初始化的,然后使用operator=进行复制。
  • operator=也有同样的问题;它应该接受引用而不是指针。

operator=中“重用”拷贝构造函数的传统方法是使用拷贝并交换技巧。我建议使用这种方式来实现类。


太好了,说得好。谢谢。 - Robb
请记住,使用复制和交换并不能解决上述任何问题。特别是,提到的低效仍然存在。尽管如此,复制和交换在设计展现强异常保证的类时非常有用,因此这是一个很好的实践方法。 - John Dibling

2
个人而言,我认为这不是一个好的实践。
对于构造函数来说,很难想到一个将指向对象的指针隐式转换为对象本身会有用的地方。
指针没有必要是非常量的,如果您有可用的类指针,那么解引用它并使用复制构造函数明确说明您想要复制对象的意图并不难。
同样,对于非标准赋值运算符,为什么要允许从指针进行赋值,当正确在调用点对其进行解引用更清晰、更符合习惯呢?

2
我认为比目前讨论过的问题更重要的问题是,您的非标准赋值运算符并不会阻止编译器生成标准赋值运算符。既然您已经决定需要创建一个赋值运算符(因为您已经创建了复制构造函数),那么默认情况几乎肯定是不足够的。因此,这个类的用户在看似对任何人来说都是非常基本和标准的对象使用期间可能会遇到这个问题。

1

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

赋值运算符和接受类型指针的构造函数 - 特别是可以用于隐式转换的构造函数 - 会使事情变得混乱,并且很有可能创建意外的副本,这不仅可能成为性能问题,还可能导致错误。

我想不出任何好的理由,为什么你会想要在类型指针和类型本身之间进行隐式或显式转换。内置的方法是对对象进行解引用。我想可能有一些我想不到的特定情况需要这种操作或者这是一个好主意,但我真的很怀疑。除非你有具体而充分的理由这样做,否则我强烈建议不要这样做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接