创建与构造函数参数无关的对象指针

时间:2012-11-01 05:16:18

标签: c++ pointers constructor placement-new

我正在尝试创建一个像容器Vector这样的矢量。

然后声明:

Vector< A> Avector.

在分配内存时,它会产生编译错误,即A没有默认构造函数。 我编写了以下代码来分配内存。

char *pBuffer = (char*) malloc(size*sizeof(T));
  T *array;
   for(int i = 0; i < size; i++)
  {
    (array+i) = new(pBuffer + i) T;
  }
  return array;

T是模板变量。

错误是由于在放置new时我使用T的默认构造函数,而我没有为A编写默认构造函数。

我想知道,有没有办法使内存分配不依赖于构造函数签名。

2 个答案:

答案 0 :(得分:2)

在C ++中,调用new会做两件事:

  1. 为正在创建的对象分配足够的内存&amp;
  2. 通过调用其构造函数来提供正确初始化对象的机会。
  3. 这是C ++作为一种语言的基本设计特性,为了克服仅分配内存的malloc行为,pt 2被明显地添加。

    简而言之,你无法改变这种行为。

答案 1 :(得分:1)

内存分配不依赖于构造函数签名。它是初始化

即使在您的示例中,分配也由malloc执行,而不调用任何构造函数。这是初始化(由placement-new执行),需要使用构造函数。

如果不调用其构造函数,则无法初始化用户定义的对象。

但是,至少在C ++ 11中,您可以做的是将代码放入一个函数中,该函数将构造函数所需的参数作为rvalue-references,并将它们传递给构造函数调用。放置新的。这样,你的函数调用者可以传递正确的参数。如果没有传递参数,则将调用默认构造函数。

这实际上是新std::vector的{​​{3}}所使用的技术:

template< class... Args >
void emplace_back( Args&&... args );

它是一个可变参数模板,因此任何数量的参数(零或更多)都是可能的。 Rvalue-references用于获取它们,并且在实现中你必须使用std::forward来调用构造函数以确保参数按原样传递:

(array+i) = new (pBuffer + i) T(std::forward<Params>(args)...);

所以这仍然需要使用构造函数,但是它让调用者选择构造函数(通过选择参数)。如果没有可用的默认构造函数,则调用者只需提供调用非默认构造函数所需的参数。