使用placement new初始化基类是否有效? [英] Is it valid to initialize a base class with placement new?

查看:45
本文介绍了使用placement new初始化基类是否有效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个类Base,然后这个:


struct派生:public Base

{

AnotherClass成员;

};


还假设我正在分配一个''Derived''类型的对象,其中包含

自定义分配器,无论出于何种原因,我都不想调用''Derived''的

构造函数,而是想通过
$ b $来构建对象b首先为''Base'创建一个新的位置,然后为

''成员'创建另一个。 (是的,我知道这可能听起来像是一个愚蠢的事情,但是只要幽默我,请。)这样做是否有效?


代码是这样的:


派生* ptr = allocator.allocate(1);

new(static_cast< Base *> (ptr))Base(baseParameters);

new(& ptr-> member)AnotherClass(otherParameters);


这个编译(并且没有' 崩溃,但它有效吗?

解决方案

9月3日,22:17,Juha Nieminen< nos ... @ thanks .invalidwrote:


*假设我有一个类Base,然后这个:


struct派生:public Base

{

* * AnotherClass会员;


};


*同时假设我正在用一个

自定义分配器分配一个''Derived''类型的对象,无论出于何种原因,我都不想打电话给

的构造函数''派生'',但我想通过

来构建对象,首先为''Base'创建一个新的位置,然后为

''创建另一个会员''。 (是的,我知道这可能听起来像是一个愚蠢的事情,但是只要幽默我,请。)这样做是否有效?


*代码如下:


派生* ptr = allocator.allocate(1);

new(static_cast< Base *> ;(ptr))Base(baseParameters);

new(& ptr-> member)AnotherClass(otherParameters);


*这个编译(和并没有崩溃,但它有效吗?



编号如果会员属于Derived,则不会。

在任何情况下,您都没有创建Derived对象:为此,您

必须调用派生的构造函数。或许更有意义描述你想要完成的事情?


/ Peter


< blockquote> peter koch写道:


> Derived * ptr = allocator.allocate(1);
new(static_cast< ; Base *>(ptr))Base(baseParameters);
new(& ptr-> member)AnotherClass(otherParameters);

这个编译(并没有崩溃) ),但它有效吗?



编号如果会员属于Derived,则不会。



我上面写的这些行与以下不同:


派生* ptr = new派生;


(当然,假设Derived的构造函数将

''baseParameters''传递给Base,将''otherParameters'传递给''member'',并且

''allocator''是默认的分配器。)


换句话说,''new''做那些三行的东西我上面引用的
不是吗?


无论如何,你还没有创建Derived对象:要做到这一点,你需要/>
必须调用派生的构造函数。或许更有意义描述你想要完成的事情?




我想要完成的是一些很容易的事情,可以使用C ++ 0x的可变参数模板解决这个问题。简单的方法

将一堆值转发给''member'的构造函数,而不需要在''Derived''结构中编写大量的构造函数。
(这可以通过在

''派生''结构中放置一个可变参数模板构造函数来实现,但直到C ++ 0x被批准并由

编译器,我不得不求助于丑陋的技巧。)


也就是说,我正在尝试将不同数量的参数传递给
$ b ''member''的$ b构造函数(来自外部模板类),并且使用

placement new我可以用一行代码完成。通过适当的构造''衍生'的'b $ b'机制,我必须为它编写一大堆模板

构造函数,每个可能的参数数量一个。它当然是可能的b $ b,但是很乏味。


(不,调用复制构造函数或''成员''的副本分配
在这种情况下不是一个选项。如果是,那将是一个

清洁解决方案。)


9月4日,12:23 * am,Juha Nieminen< nos ... @ thanks.invalidwrote:


*我上面写的这些行与我们的不同之处:


派生* ptr = new派生;


(当然,假设Derived的构造函数通过了

''baseParameters''到Base,''otherParameters''到''member'',并且

''allocator''是默认的分配器。)


*换句话说,''new''做的是上面引用的那三行我不是b $ b吗?



是的,确实如此。它调用Derived对象构造函数。除此之外,

在结构化之前它初始化了一个对象,即设置

内部数据有关基本类型的信息(对于dynamic_cast)

和vtable(如果你有虚拟方法)。


在你的例子中,你根本没有创建一个Derived对象,所以你已经获得了一个基本类型,并带来了所有后果。你只有内存

分配。


Robert


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.allocate(1);
new (static_cast<Base*>(ptr)) Base(baseParameters);
new (&ptr->member) AnotherClass(otherParameters);

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

解决方案

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.allocate(1);
new (static_cast<Base*>(ptr)) Base(baseParameters);
new (&ptr->member) AnotherClass(otherParameters);

* 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


peter koch wrote:

>Derived* ptr = allocator.allocate(1);
new (static_cast<Base*>(ptr)) Base(baseParameters);
new (&ptr->member) AnotherClass(otherParameters);

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 ''otherParameters'' 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.)


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 ''otherParameters'' 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 "initializes" 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


这篇关于使用placement new初始化基类是否有效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆