具有聚合初始化的 C++11 构造函数委托
Posted
技术标签:
【中文标题】具有聚合初始化的 C++11 构造函数委托【英文标题】:C++11 constructor delegation with aggregate initialization 【发布时间】:2016-10-02 06:23:42 【问题描述】:是否可以在我自己定义的默认 ctor 中调用聚合初始化?
GCC 使用以下代码抱怨“错误:构造函数委托给自身”:
struct X
int x, y, z, p, q, r;
X(): x, y, z, p, q, r // cumbersome
//X(): X // the idea is nice but doesn't compile
;
我现在在 ctor 正文中使用memset(this, 0, sizeof(*this))
。
【问题讨论】:
如果X
本身不必是聚合,您可以将 x, y, z...
移动到基类,并在成员初始化列表中聚合初始化该基类
@PiotrSkotnicki 很有趣的想法,但如果我在生产代码中这样做,我的同事们会皱眉头。
memset(this, 0, sizeof(*this)) 正在伤害我内心的平静...
【参考方案1】:
使用factory pattern - 将构造函数的主体移动到单独的类:
struct X
int x, y, z, p, q, r;
;
struct XFactory
X create();
;
X XFactory::create()
X x;
// do needed modification
return x;
虽然我总是更喜欢工厂模式 - 还有其他方式更符合您的明确需求 - 为您的每个成员数据定义默认构造函数:
template <typename T>
struct DefaultConstructibleData
T data;
DefaultConstructibleData() data
;
并使用它:
struct X
DefaultConstructibleData<int> x, y, z, p, q, r;
X()
// do whatever you needs to do
// all x,y,... are already constructed to their defaults
;
【讨论】:
大量冗余复制。而且它不会删除 OP 抱怨的任何繁琐代码,只是将其移到 c'tor 之外。 @StoryTeller RVO - en.wikipedia.org/wiki/Return_value_optimization - 防止重复复制... RVO 是一种优化(不是保证),如果你做作业,至少必须有一个副本。更不用说,您无法创建 const 对象。 我在前面的 const 对象上得到了纠正。有一瞬间的困惑。但是您的副本并未全部优化。从语义上讲,编译器无法做到这一点。这就是最初发明 move c'tor 的原因。 @StoryTeller 即使 RVO 在这里不起作用(它不适用于复制类),那么这里的 x 这里是过期值 - 所以移动构造函数将在这里自动调用 - 没有复制......除非移动未定义。当然对于填充 int 的结构 - RVO 实际上总是在工作......【参考方案2】:一种方法是通过以下方式欺骗重载决议:
struct X
int x, y, z, p, q, r;
X(int) : x, y, z, p, q, r
X() : X(0)
;
另一种方法是使用类内默认成员初始化:
struct X
int x = 0, y = 0, z = 0, p = 0, q = 0, r = 0;
;
在您的具体示例中,您也可以这样做:
struct X
std::array<int, 6> vars;
;
【讨论】:
我认为 OP 打算完全删除x, y, z, p, q, r
部分
@PiotrSkotnicki OP 说他/她现在正在使用 memset(this, 0, sizeof(*this))
不,OP 基本上是问如何在 C++ 中复制 Java 的 this() condtructor 调用
@101010 是的,所以他想用一个函数初始化分配结构的部分内存(结构内部的变量)。所以你们都做对了。【参考方案3】:
您可以使用 CRTP 来执行此操作。
template<class C>
struct ZeroInitialized
ZeroInitialized() memset((C*)this, 0, sizeof(C));
;
struct A : ZeroInitialized<A>
int x, y, z, p, q, r;
;
但我不保证这是安全的。
【讨论】:
这不是我的意思 :( 。聚合初始化是指struct A : B A() : B ;
和 struct B int x, y, z; ;
@PiotrSkotnicki,你的意思是将成员推到基础上,但它并没有解决 OP 的问题,只是重命名了它出现的类。我合并了这两种方法。
@PiotrSkotnicki,很好,在这个可憎的事情上没有提到你 :)以上是关于具有聚合初始化的 C++11 构造函数委托的主要内容,如果未能解决你的问题,请参考以下文章
[C++11 类的改进] --- 继承构造函数和委托构造函数