我正在研究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;
返回此信息,这是正确的。
42
84
显然这是一个非常简单的例子,但除了内存效率低下(两个A
创建,另一个被另一个覆盖之前被破坏),可能会出现什么问题?它当然看起来像代码味道,但我想不出一个非常好的理由。
答案 0 :(得分:1)
您没有使用整数初始化对象,而是修改默认的初始化对象。这可能是也可能不是问题。通常人们会将某些init()
函数中的常见内容视为具有与委托ctors类似的功能。但是,在某些情况下,这是不希望/错误/不可能的:
此外,这被一些人认为是不好的风格。我个人认为这种风格很糟糕,因为我认为你应该总是初始化而不是稍后分配,即使对于简单的情况,因为有一天你会忘记一个重要案例,然后失去的表现会让你感到厌烦。
但是YMMV。
答案 1 :(得分:0)
你的代码实际上并不是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,但你可能不想这样做。)