473,785 Members | 2,349 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Is it valid to initialize a base class with placement new?

Assume I have a class Base, and then this:

struct Derived: public Base
{
AnotherClass member;
};

Also assume that I'm allocating an object of type 'Derived' with a
custom allocator and that, for whatever reason, I don't want to call the
constructor of 'Derived', but instead I want to build the object by
first making a placement new for the 'Base' and then another for the
'member'. (Yes, I know this might sound like a bit of a silly thing to
want, but just humor me, please.) Is it valid to do that?

The code would be something like this:

Derived* ptr = allocator.alloc ate(1);
new (static_cast<Ba se*>(ptr)) Base(baseParame ters);
new (&ptr->member) AnotherClass(ot herParameters);

This compiles (and doesn't crash), but is it valid?
Sep 3 '08 #1
19 1930
On 3 Sep., 22:17, Juha Nieminen <nos...@thanks. invalidwrote:
* Assume I have a class Base, and then this:

struct Derived: public Base
{
* * AnotherClass member;

};

* Also assume that I'm allocating an object of type 'Derived' with a
custom allocator and that, for whatever reason, I don't want to call the
constructor of 'Derived', but instead I want to build the object by
first making a placement new for the 'Base' and then another for the
'member'. (Yes, I know this might sound like a bit of a silly thing to
want, but just humor me, please.) Is it valid to do that?

* The code would be something like this:

Derived* ptr = allocator.alloc ate(1);
new (static_cast<Ba se*>(ptr)) Base(baseParame ters);
new (&ptr->member) AnotherClass(ot herParameters);

* This compiles (and doesn't crash), but is it valid?
No. Not if member belongs to Derived.
In any case, you have not created a Derived object: To do this you
must call the contructor of derived. Perhaps it would make more sense
to describe what you are trying to accomplish?

/Peter
Sep 3 '08 #2
peter koch wrote:
>Derived* ptr = allocator.alloc ate(1);
new (static_cast<Ba se*>(ptr)) Base(baseParame ters);
new (&ptr->member) AnotherClass(ot herParameters);

This compiles (and doesn't crash), but is it valid?

No. Not if member belongs to Derived.
How exactly are those lines I wrote above different from:

Derived* ptr = new Derived;

(assuming, of course, that the constructor of Derived passes the
'baseParameters ' to Base and the 'otherParameter s' to 'member', and that
'allocator' is the default allocator.)

In other words, does the 'new' do something that those three lines I
quoted above don't?
In any case, you have not created a Derived object: To do this you
must call the contructor of derived. Perhaps it would make more sense
to describe what you are trying to accomplish?
What I'm trying to accomplish is something which would be easily
solvable with variadic templates of C++0x, namely an easy way of
forwarding a bunch of values to the constructor of 'member' without
having to write a ton of constructors in the 'Derived' struct. (This
would be easy by putting a variadic template constructor in the
'Derived' struct, but until C++0x is ratified and implemented by
compilers, I have to resort to uglier tricks.)

Namely, I'm trying to pass a varied amount of parameters to the
constructor of 'member' (from within an outer template class), and with
placement new I can do that with a one-liner. With a proper construction
mechanism of 'Derived' I would have to write a big bunch of template
constructors for it, one for each possible amount of parameters. It
would of course be possible, but tedious.

(And no, calling the copy constructor or copy assignment of 'member'
is not an option in this case. If it would be, then that would be a
cleaner solution.)
Sep 3 '08 #3
On Sep 4, 12:23*am, Juha Nieminen <nos...@thanks. invalidwrote:
* How exactly are those lines I wrote above different from:

Derived* ptr = new Derived;

(assuming, of course, that the constructor of Derived passes the
'baseParameters ' to Base and the 'otherParameter s' to 'member', and that
'allocator' is the default allocator.)

* In other words, does the 'new' do something that those three lines I
quoted above don't?
Yes, it does. It calls a Derived object constructor. Besides that,
before the conctructor it "initialize s" an object, i.e. sets up the
internal data such information about the base type (for dynamic_cast)
and vtable (in case you had virtual methods).

In your example you didn't created a Derived object at all so you've
got a Base type with all consequences of that. You only got memory
allocated.

Robert
Sep 4 '08 #4
On Sep 4, 12:23 am, Juha Nieminen <nos...@thanks. invalidwrote:
peter koch wrote:
Derived* ptr = allocator.alloc ate(1);
new (static_cast<Ba se*>(ptr)) Base(baseParame ters);
new (&ptr->member) AnotherClass(ot herParameters);
This compiles (and doesn't crash), but is it valid?
No. Not if member belongs to Derived.
How exactly are those lines I wrote above different from:
Derived* ptr = new Derived;
It calls the constructor of Derived.
(assuming, of course, that the constructor of Derived passes
the 'baseParameters ' to Base and the 'otherParameter s' to
'member', and that 'allocator' is the default allocator.)
In other words, does the 'new' do something that those three
lines I quoted above don't?
It calls the construtor of Derived. It does NOT call the
constructor of Base, nor does it call the constructor of member;
these are called by the constructor of Derived. (The
constructor of Derived may, and often does, other things as
well.)

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 4 '08 #5
James Kanze wrote:
On Sep 4, 12:23 am, Juha Nieminen <nos...@thanks. invalidwrote:
>peter koch wrote:
>>>Derived* ptr = allocator.alloc ate(1);
new (static_cast<Ba se*>(ptr)) Base(baseParame ters);
new (&ptr->member) AnotherClass(ot herParameters);
>>> This compiles (and doesn't crash), but is it valid?
>>No. Not if member belongs to Derived.
>How exactly are those lines I wrote above different from:
>Derived* ptr = new Derived;

It calls the constructor of Derived.
>(assuming, of course, that the constructor of Derived passes
the 'baseParameters ' to Base and the 'otherParameter s' to
'member', and that 'allocator' is the default allocator.)
>In other words, does the 'new' do something that those three
lines I quoted above don't?

It calls the construtor of Derived. It does NOT call the
constructor of Base, nor does it call the constructor of member;
these are called by the constructor of Derived. (The
constructor of Derived may, and often does, other things as
well.)
I still fail to see how the end result is different from what I wrote.

'Derived' has no explicit constructor, and thus only the
compiler-generated one. Also, 'Derived' has no member functions, and the
object of type 'Derived' is never used for anything else than to access
the base class function and the function of 'Member'. The destructor of
'Derived' is never called either (because I never call it explicitly nor
implicitly).

So basically the situation is that I have allocated space for an
object of type 'Base', with space for an object of type 'AnotherClass'
appended to it, and then I construct that 'Base' object with placement
new, as well as the 'member' object. The 'Derived' struct is only a
placeholder for this allocated memory, and never used for anything else.

So what is it that makes it illegal to do so?

(Why not simply have an object of type Base and another of type
AnotherClass and construct them normally? Because if Base is an empty
class, the compiler cannot perform empty base optimization.)
Sep 4 '08 #6
On Sep 4, 3:44 pm, Juha Nieminen <nos...@thanks. invalidwrote:
James Kanze wrote:
On Sep 4, 12:23 am, Juha Nieminen <nos...@thanks. invalidwrote:
peter koch wrote:
Derived* ptr = allocator.alloc ate(1);
new (static_cast<Ba se*>(ptr)) Base(baseParame ters);
new (&ptr->member) AnotherClass(ot herParameters);
>> This compiles (and doesn't crash), but is it valid?
>No. Not if member belongs to Derived.
How exactly are those lines I wrote above different from:
Derived* ptr = new Derived;
It calls the constructor of Derived.
(assuming, of course, that the constructor of Derived passes
the 'baseParameters ' to Base and the 'otherParameter s' to
'member', and that 'allocator' is the default allocator.)
In other words, does the 'new' do something that those three
lines I quoted above don't?
It calls the construtor of Derived. It does NOT call the
constructor of Base, nor does it call the constructor of
member; these are called by the constructor of Derived.
(The constructor of Derived may, and often does, other
things as well.)
I still fail to see how the end result is different from what
I wrote.
Try it. Formally, it's undefined behavior, so the results may
vary. But suppose Base is a polymorphic class (otherwise, why
inherit). And suppose that you then assign your pointer to a
Base*, and use typeid on it. What do you get?
'Derived' has no explicit constructor, and thus only the
compiler-generated one.
And? The compiler generated one may still have something it
needs to do.
Also, 'Derived' has no member functions, and the object of
type 'Derived' is never used for anything else than to access
the base class function and the function of 'Member'. The
destructor of 'Derived' is never called either (because I
never call it explicitly nor implicitly).
So basically the situation is that I have allocated space for
an object of type 'Base', with space for an object of type
'AnotherClass' appended to it, and then I construct that
'Base' object with placement new, as well as the 'member'
object. The 'Derived' struct is only a placeholder for this
allocated memory, and never used for anything else.
In which case, there shouldn't be any problem, if they're only
place holders, and you never use the object as a Derived. But I
don't see any case where I'd want to do that; if I just wanted
to group objects, I'd use a struct.
So what is it that makes it illegal to do so?
The standard. And the way most compilers implement inheritence.
(Why not simply have an object of type Base and another of
type AnotherClass and construct them normally? Because if Base
is an empty class, the compiler cannot perform empty base
optimization.)
Which it might not do anyway?

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Sep 4 '08 #7
James Kanze wrote:
But I
don't see any case where I'd want to do that; if I just wanted
to group objects, I'd use a struct.
Except that if 'Base' is made a member variable of the struct, the
compiler won't be able to perform empty base class optimization (which
in this case is relevant).
Sep 4 '08 #8
Juha Nieminen schrieb:
James Kanze wrote:
>But I
don't see any case where I'd want to do that; if I just wanted
to group objects, I'd use a struct.

Except that if 'Base' is made a member variable of the struct, the
compiler won't be able to perform empty base class optimization (which
in this case is relevant).
There is no empty base class optimization. You create an object of type
Base and an object of type AnotherClass. Neither is a base class of the
other.
Base would be a base class of Derived, but there is no object of type
Derived, because you don't create one. How should the compiler handle
empty base class optimization, when there is no object of a type with an
empty base class?

However, why don't you simple do:
new (static_cast<vo id*>(ptr)) Derived(paramet ers);
?

--
Thomas
Sep 4 '08 #9
On Sep 4, 7:23 am, Juha Nieminen <nos...@thanks. invalidwrote:
peter koch wrote:
Derived* ptr = allocator.alloc ate(1);
new (static_cast<Ba se*>(ptr)) Base(baseParame ters);
new (&ptr->member) AnotherClass(ot herParameters);
In other words, does the 'new' do something that those three lines I
quoted above don't?
Might do - up to the compiler - but can't see any reason given the
obvious non-polymorphic requirement.
What I'm trying to accomplish is something which would be easily
solvable with variadic templates of C++0x, namely an easy way of
forwarding a bunch of values to the constructor of 'member' without
having to write a ton of constructors in the 'Derived' struct. (This
would be easy by putting a variadic template constructor in the
'Derived' struct, but until C++0x is ratified and implemented by
compilers, I have to resort to uglier tricks.)

Namely, I'm trying to pass a varied amount of parameters to the
constructor of 'member' (from within an outer template class), and with
placement new I can do that with a one-liner. With a proper construction
mechanism of 'Derived' I would have to write a big bunch of template
constructors for it, one for each possible amount of parameters. It
would of course be possible, but tedious.

(And no, calling the copy constructor or copy assignment of 'member'
is not an option in this case. If it would be, then that would be a
cleaner solution.)
You've really got that many arguments? And/or doing this in enough
classes for it to become tedious? Impressive.

Just use a preprocessor macro (assuming you're using a capable
compiler)...

Tony
Sep 5 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
3640
by: Tao | last post by:
I just upgraded .NET framework to 1.1 and VS.Net to 2003 version and tried to test it out. I created an ASP.NET project using the wizard and tried to run it by hitting "F5". I got an exception: "Specified cast is not valid." The only thing i put there was a "test this." inside the form. What might be the problem here? Thanks in advance. The Exception:
8
1432
by: block111 | last post by:
I'm a student in a university and today we had a final exam in c++. Basicly, I was amazed by the amount of lame and invalid examples/questions. There was a question that in practice works but is a really big mistake (as far as I'm concerned). So, I'll need to prove why exactly it was wrong. Here is the example: int *p1, *p2, x = 3; p1 = new int; *p1 = 60;
5
2929
by: removeps-generic | last post by:
Hi. I'm using placement new to re-initialize part of an object. Is this OK? struct BaseImp { All& r_all; BaseImp(All& all) : r_all(all) }; struct Calc::Imp : public BaseImp
18
4216
by: toton | last post by:
Hi, In C++ when I initialize an array it, also initializes the class that it contains, which calls the default constructor. However, I want to initialize the array only (i.e reserve the space) and use my specific constructor to initialize the class. How to do it without using malloc? Something like Point* pt = new Point; I want it to reserve the space for N points only, and not to call default constructor. I dont have a default...
15
3537
by: Juha Nieminen | last post by:
I'm sure this is not a new idea, but I have never heard about it before. I'm wondering if this could work: Assume that you have a common base class and a bunch of classes derived from it, and you want to make a deque which can contain any objects of any of those types. Normally what you would have to do is to make a deque or vector of pointers of the base class type and then allocate each object dynamically with 'new' and store the...
11
2336
by: Bob Altman | last post by:
Hi all, I have a class that contains a member variable that is an array of class instances: class MyClass { private: SomeClass m_someClass; SomeClass m_arrayOfClasses; };
0
9646
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10346
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10157
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8982
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7504
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6742
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5514
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4055
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3658
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.