分配给*this以进行构造函数委派

Assign to *this for constructor delegation

本文关键字:构造函数 委派 this 分配      更新时间:2023-10-16

我正在研究C++11中的一些新功能,由于我当前版本的GCC,我无法使用构造函数委托。但它让我开始考虑复制这样的功能:

class A
{
public:
    A() : num( 42 ) {}
    A( int input ) { *this = A(); num *= input; }
    int num;
};

它当然可以编译并运行良好,代码如下:

A a;
cout << "a: " << a.num << endl;
A b( 2 );
cout << "a: " << b.num << endl;

返回正确的this。

42
84

显然,这是一个非常琐碎的例子,但除了内存效率低下(创建了两个A,其中一个在被销毁之前被另一个覆盖)之外,还会出现什么问题?它看起来确实像是一股代码的味道,但我想不出真正好的理由。

您不是用整数初始化对象,而是修改默认的初始化对象。这可能是个问题,也可能不是个问题。通常情况下,人们在某些init()函数中考虑一些常见的东西,使其具有与委托代理类似的功能。然而,在某些情况下,这是不希望的/错误的/不可能的:

  • 当你有一个引用成员时,你必须在ctor中初始化它,你不能默认初始化它,然后重写。使用指针会有所帮助
  • 对于某些成员,默认初始化会起到一些作用,而覆盖会起到额外的作用。就性能而言,立即初始化成员会更有效。根据初始化的操作,这可能只是性能上的问题,但对于对象的某些副作用,它甚至可能是平面错误
  • 该成员可能不可分配

此外,有些人认为这是一种糟糕的风格。我个人认为这是一种糟糕的风格,因为我认为你应该总是初始化,而不是稍后分配,即使是对于简单的情况,因为有一天你忘记了一个重要的情况,然后失去的性能会影响你。

但是YMMV。

您的代码实际上根本不是C++11。我在想,移动构造函数是否可以在这里工作,因为你本质上是将一个A移动到另一个,然后稍微修改它。

与C++03一样,您可以通过将构造函数放入一个子类或基类(通常带有受保护或私有继承,因为这是一个实现细节)来优化您想要在所有构造函数中执行一次的初始化。使用基类:

class ABase
{
protected:
  int num;
  ABase() : num(42) {}
};
class A : protected ABase
{
public:
   A() = default; // or in C++03 just {}
   explicit A(int input) : ABase()
   {
       num *= input;
   }
};

(您可以根据口味修改您的访问权限)。这里的问题是,我只创建过一个"ABase"对象,如果它不仅仅有一个微不足道的int成员,那可能很重要。我非常喜欢继承性,因为我在A中使用它作为类成员,而不是某个聚合对象的成员。我更喜欢这里的继承性受保护或私有,但有时如果基类有我想成为公共的成员,我会使用公共继承性,但给基类一个受保护的析构函数。这是假设没有v表,因此不需要进一步的推导。(实际上,您可以通过使继承成为虚拟的和私有的来在这里完成A,但您可能不想这样做)。