Using the new placement to invoke the constructor inside the constructor

fought these days.

The problem is calling the constructor.

I wrote a piece of code, for example:

#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 built the Foo object outside using the default constructor:

 Foo* f = new Foo(); 

I suppose the variable _n is 5, but it is NOT.

This is normal in Java, but NOT in C ++.

Also in Visual C ++ 6 sp 6,

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

work.

However, this expression rejects gcc / g ++ 4.

Finally, I found a solution.

A simple change to the default constructor in

 Foo() {Foo(5);} 

in

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

solves the problem.

What does "this" do in parentheses?

+4
source share
5 answers

What (this) does is create a new Foo object, at the location this points to (this is called new placement). You should use it only in char and unsigned char arrays, nowhere else (and almost never exists). Since you are building Foo in the place where this has already begun to build, what you are doing is undefined behavior and there will be a drain of resources all over the place if you have base classes. Historically, the normal thing is to simply translate initialization into 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. According to Apache , it is supported by GCC 4.7 and Clang 3.0, but not yet Intel C ++ or VC ++.

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

The code you started with Foo() { Foo(5);} starts with building this , then creates a new new Foo object on the stack with parameter 5, then destroys it, and then considers it to be completely constructed, without initializing which Either of these are own values. That is why it compiled and worked, but did nothing.

+4
source

In C ++ 11, you specify this using the delegation constructor:

 Foo() : Foo(5) { } 
+3
source

In parentheses (this) means that the new statement will use the this address as the address to initialize the class.

This is very dangerous: you are in the constructor of the current object and you call the new constructor in the same memory space. Imagine what happens if you inherit another class!

As for your problem, you cannot call another overloaded constructor from the constructor. A typical solution is to initialize your class:

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

I had the same problem: Another request to initialize a C ++ object ; Feel free to look at the solution.

+1
source

The correct syntax in C ++ is

 class Foo { private: int _n; public: Foo() : Foo(5) {} Foo(int n) _n(n) {} // As suggested by another member edit, initializer lists are preferred }; 

Alternatively, C ++ allows default parameter values, e.g.

 Foo(int n = 5); 

This allows you to write one constructor, not two.

In addition, you should definitely learn about the difference between built-in and non-built-in functions. This Java programming style is valid C ++, but it has pros and cons along with at least one other alternative.

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

- This is the "post new" operator, which calls the constructor in the previously allocated memory.

Now, another question for you - C ++ 11 allows for exactly this (calling constructors from each other), but the earlier standard (especially the one used by MSVC 6) does not, so using these ugly init() methods is the way to go you.

0
source

All Articles