使用placementnew在构造函数中调用构造函数
Using placement new to call constructor within constructor
这些天一直在挣扎。
问题出在构造函数调用上。
我写了一段代码,比如:
#include <iostream>
using namespace std;
class Foo
{
private: int _n;
public:
Foo() { Foo(5);}
Foo(int n) {_n=n; cout << n << endl; }
};
int main()
{
Foo* foo = new Foo();
return 0;
}
当我在外部使用默认构造函数构建Foo对象时:
Foo* f = new Foo();
我假设变量_n是5,但它不是。
这在Java中可以,但在c++中不行。
此外,在Visual C++6 sp 6中,
Foo() {this->Foo(5);}
工作。
然而,这个表达式被gcc/g++4拒绝了。
最后,我找到了解决办法。
只需将默认构造函数更改为
Foo() {Foo(5);}
进入
Foo() { new (this) Foo(5); }
解决了问题。
括号中的"this"做什么?
(this)
所做的是在this
指向的位置创建一个全新的Foo
对象(这称为放置新对象)。您应该只在char
和unsigned char
的数组中使用它,而不在其他数组中使用(而且几乎从不在其他数组)。由于您正在this
已经开始构建的位置构建Foo
,因此您所做的是未定义的行为,并且如果您有基类,则会到处泄漏资源。从历史上看,通常的做法只是将初始化转移到一个私有函数。
class Foo {
public:
Foo() { init(5);}
Foo(int n) {init(n);}
private:
int _n;
void init(int n) {
_n=n;
};
}
在C++11中,构造函数应该能够用这种语法相互调用,但我还不知道哪些编译器支持这种语法。根据Apache的说法,它得到了GCC 4.7和Clang 3.0的支持,但还没有得到英特尔C++和VC++的支持。
class Foo {
public:
Foo() : Foo(5) {}
Foo(int n) {_n=n;}
private:
int _n;
}
从Foo() { Foo(5);}
开始的代码开始构造this
,然后在堆栈上用参数5创建一个全新的Foo
对象,然后销毁它,然后认为自己完全构造好了,而没有初始化它自己的任何值。这就是为什么它编译并运行,但似乎什么都没做。
在C++11中,您可以使用委托构造函数来指定它
Foo() : Foo(5) { }
括号中的(this)
表示新运算符将使用this
的地址作为初始化类的地址。
这是非常危险的:您在当前对象的构造函数中,并且在同一内存空间上调用一个新的构造函数。想象一下,如果你从另一个类继承,会发生什么!
至于您的问题,不能从构造函数中调用另一个重载构造函数。典型的解决方案是有一个初始化类的方法:
class Foo
{
int _n;
public:
Foo() { init(5); }
Foo( int i) { init(i); }
void init(int i) { _n = i; }
};
我在这里遇到了同样的问题:又一次C++对象初始化询问;请随意查看解决方案。
Foo() { new (this) Foo(5); }
是一个"placement-new"运算符,它在预先分配的内存上调用构造函数。
现在,对于你的另一个问题——C++11完全允许这样做(从另一个调用构造函数),但早期的标准(尤其是MSVC 6使用的标准)没有,所以使用那些丑陋的init()
方法是你的选择。
C++中的正确语法是
class Foo {
private: int _n;
public:
Foo() : Foo(5) {}
Foo(int n) _n(n) {} // As suggested by another member's edit, initializer lists are preferred
};
或者,C++允许默认参数值,例如
Foo(int n = 5);
这允许您编写一个构造函数,而不是两个构造函数。
此外,您应该了解内联函数和非内联函数之间的区别。这种Java风格的编程是有效的C++,但它有优缺点,还有至少一种其他选择。
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 确保所有构造函数调用相同的函数 c++ 设计模式
- 减少复制构造函数调用
- 使用回调函数从构造函数调用虚拟/派生方法的替代方法?
- 在 Google 测试中,我可以从构造函数调用 GetParam() 吗?
- C++ - 从另一个类构造函数调用类构造函数
- 在C++中初始化带有和不使用构造函数调用的对象有什么区别
- 是否可以从移动构造函数调用默认构造函数?
- 在模板生成器模式中分解重复的构造函数调用
- std::atexit 从全局对象的构造函数调用时的排序
- 对构造函数调用的约束
- 编译器错过了无效的构造函数调用,并调用不存在的(或私有的)默认构造函数
- 用构造函数调用填充向量
- 创建指针时是否没有构造函数调用
- 使用 emplace_back 避免移动构造函数调用的最佳方法?
- C++ 抽象类构造函数调用
- 为什么函数参数将带有参数的构造函数调用
- 为什么比“构造函数”调用更多的“解构器”调用
- 将对象传递给函数并不是导致构造函数调用