Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using placement new to call constructor within constructor

was struggling these days.

The problem is the constructor calling.

I wrote a piece of code like:

#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;

}

When I constructed a Foo object outside using the default constructor:

Foo* f = new Foo();

I suppose variable _n is 5, however, it's NOT.

It's ok in Java but NOT in c++.

In addition, in Visual C++ 6 sp 6,

Foo() {this->Foo(5);}

works.

However, this expression is refused by gcc/g++ 4.

Finally, I found out the solution.

Simply changing the default constructor into

Foo() {Foo(5);}

into

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

solves the problem.

What does "this" in parentheses do?

like image 912
bsb3166 Avatar asked Feb 19 '23 19:02

bsb3166


1 Answers

What the (this) does, is creates a brand new Foo object, at the place pointed at by this (this is called placement new). You should only use it in arrays of char and unsigned char, nowhere else (and almost never there either). Since you are constructing a Foo at the location where this has already started construction, what you are doing is undefined behavior, and would leak resources all over the place if you had base classes. Historically, the normal thing to do is merely move the initialization to a private function.

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

In C++11 constructors should be able to call each other with this syntax, but I don't know which compilers support it yet. According to Apache, it's supported by GCC 4.7 and Clang 3.0, but not yet Intel C++ nor VC++.

class Foo {
public:    
  Foo() : Foo(5) {}
  Foo(int n) {_n=n;}
private: 
  int _n;
}

The code you started with Foo() { Foo(5);} begins construction of this, then creates a brand new Foo object on the stack with the parameter 5, then destroys it, and then considers itself completely constructed, without initializing any of it's own values. That is why it compiled and ran, but didn't appear to do anything.

like image 194
Mooing Duck Avatar answered May 18 '23 20:05

Mooing Duck