繁体   English   中英

使用placement new来在构造函数中调用构造函数

[英]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)确实是创造了一个全新Foo对象,在地方指着用this (这就是所谓的安置新)。 你应该只在charunsigned char数组中使用它,在其他地方(并且几乎从不在那里)。 既然你要构建Foo在其中的位置, this已经开工建设,你在做什么是不确定的行为,如果你有基类会泄漏资源得到处都是。 从历史上看,正常的做法只是将初始化移动到私有函数。

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)表示new运算符将使用this的地址作为初始化类的地址。

非常危险:您在当前对象的构造函数中,并在同一内存空间上调用新的构造函数。 想象一下,如果你从另一个类继承会发生什么!

至于你的问题,你不能从构造函数中调用另一个重载的构造函数。 典型的解决方案是使用方法初始化您的类:

class Foo
{
  int _n;
public:
  Foo() { init(5); }
  Foo( int i) { init(i); }
  void init(int i) { _n = i; }
};

我在这里遇到了同样的问题: 另一个C ++对象初始化审讯 ; 随便看看解决方案。

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 ++,但它有其优缺点以及至少一种其他替代方案。

Foo() { new (this) Foo(5); }

是一个“placement new”运算符,它在预分配的内存上调用构造函数。

现在,对于你的其他问题--C ++ 11允许完全相同(相互调用构造函数),但早期的标准(特别是MSVC 6使用的标准)没有那个,所以使用那些丑陋的init()方法是你的方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM