大括号或相等初始化与构造函数委托

brace-or-equal initialization vs constructor delegation

本文关键字:构造函数 初始化      更新时间:2023-10-16

也许我的标题可以翻译为"苹果与桔子",但我不太确定,所以我希望so社区能帮助我理解一些最佳实践。

假设我有这两个例子。

大括号或相等初始化

class foo
{
public:
  foo() {}
  foo(int a) : m_a(a) {}
  foo(int a, int b) : m_a(a), m_b(b) {}
  foo(int a, int b, int c) : m_a(a), m_b(b), m_c(c) {}
private:
  int m_a = 1;
  int m_b = 2;
  int m_c = 3;
};

构造函数委托

class foo
{
public:
  foo() : m_a(1), m_b(2), m_c(3) {}
  foo(int a) : foo() { m_a = a; }
  foo(int a, int b) : foo() { m_a = a; m_b = b; }
  foo(int a, int b, int c) : foo() { m_a = a; m_b = b; m_c = c; }
private:
  int m_a;
  int m_b;
  int m_c;
};

我觉得第一个更好,因为它不会导致变量的双重初始化。在第二个例子中,foo构造函数的最后一次重载是最糟糕的,因为每个成员变量都初始化了两次。

这里的首选方法是哪种?假设前者是首选,那么委托构造函数什么时候有用?

您希望从使用较少参数的构造函数委托给使用最多参数的构造函数,并为额外参数提供默认值:

foo( int a, int b, int c ) : m_a(a), m_b(b), m_c(c) {}
foo( int a, int b ) : foo( a, b, 3 ) {}
foo( int a ) : foo( a, 2, 3 ) {}
foo() : foo( 1, 2, 3 ) {}

正如clcto所指出的,您应该以不同的方式进行委派。

事实上,我们可以使用默认参数值做得更好(使用您给定的示例!!):

class foo
{
public:
  // no longer need all your other constructors
  foo(int a=1, int b=2, int c=3) : m_a(a),m_b(b),m_c(c){}
private:
  int m_a;
  int m_b;
  int m_c;
};

您的实际代码可能不同;即,您有时想要初始化b,而不是ac,因此您可以使用发布的其他答案之一。