0

Again with placement new I've found an example on this forum like this:

char *buf  = new char[sizeof(string)]; // pre-allocated buffer
string *p = new (buf) string("hi");    // placement new
string *q = new string("hi");          // ordinary heap allocation
  • But I think here buf is a pointer to an allocated and Constructed dynamic array of default-init characters. So the characters in the array are default initialized and have an indeterminate values.

  • I guess using the placement new in the second line will constructs objects on the previously constructed array of objects.

  • Why the user didn't call operator new on the array allocation rather than using new expression?:

     char *buf  = static_cast<char*>(operator new[](sizeof(string)));
    
  • After all I think if buff is a pointer to a dynamic array of non-default-constructible objects then the code will fail to compile using the new expression rather than using the operator new function.

  • Are my guesses correct?

Here is the link to the original answer:

What uses are there for "placement new"?

4

4 回答 4

2

为什么用户没有在数组分配上调用 operator new 而不是使用 new 表达式?:

我们无法回答这个问题,因为我们不是那个用户。您应该向用户询问 - 尽管该示例是在 1998 年编写的,但与他们联系可能并不容易。我的猜测:他们不知道非放置运算符 new 存在,或者他们不知道它的用途。在这种情况下,重用 char 数组的内存是一种直观的选择。

请注意,首先创建单个动态std::string对象的示例毫无意义(我假设string示例中就是这样)。

我有一个类似的问题给你:你为什么operator new[]在你的建议中使用而不是operator new?更重要的是,为什么不使用分配器呢?

我的猜测正确吗?

  1. 正确的。
  2. 正确的。
  3. 这是一个问题,而不是猜测。我在上面介绍过。
  4. 它会失败。但这无关紧要,因为char它是默认可构造的。
于 2021-06-05T01:32:48.550 回答
2

char是一种既基本又微不足道的对象类型。实际上,创建一个不会触及内存,而将它们组成一个数组也不会。

char* foo = new char[10];

char *foo  = static_cast<char*>(operator new[](10));

最终在机器代码中做同样的事情,除了第二个更冗长。

抽象机有一些细微的差别;在一个中创建了一堆字符,在另一个中它们不在该行上。提出一个需要相当多的语言律师努力的案例(我认为处置可能会有所不同,并且某些访问权限可能会有所不同,尤其是在 c++ 修复 malloc 问题之前的标准版本中)。

毕竟我认为如果buff是指向非默认可构造对象的动态数组的指针,那么代码将无法使用 new 表达式而不是使用 operator new 函数进行编译。

当然可以,但是演员阵容会是代码味道,重点buf是为以后的新位置存储。估计已经是了

void *foo  = operator new[](10);

不那么疯狂。

仅仅因为你可以静态转换并不意味着你应该。

于 2021-06-05T02:46:01.683 回答
1

operator new[](sizeof(string))这很奇怪,它创建对象的语法不正确。在最好的情况下,它在内存中隐式创建一个对象(如果 operator new 实现为 std::malloc 调用并且 object 是 POD 类型),而不初始化或构造一个。在这种情况下,您所能做的就是static_cast<char*>(new string);提供的行将string在动态存储中创建一个对象,然后通过将指针类型替换为char*.

问题是,对于放置 newbuf没有必要指向动态内存。它可以是一个静态缓冲区。它可以是一个指向用于存储多个对象的相当大的存储中的内存位置的指针,一个内存池。新对象将在给定位置构建。

请注意,在放置 newstd::string的情况下,数据存储仍然像往常一样 - 它在动态内存中分配字符数据。要使用一些内存池,程序员应该提供适当的分配器,这是放置 new 运算符的目的之一。

于 2021-06-05T00:04:12.663 回答
0

不, buf 不是对象数组。它是一个字符数组,所以基本上是一个字节数组。虽然它被分配了一个新的数组,但它基本上被用作字节指针。

如果你想在一个确切的位置分配一个对象,但你想遵循 C++ 对象分配的所有规则,那么使用placement new ——所以调用构造函数并设置vtables。通常的用例是如果您正在执行自己的自定义内存分配并重用现有内存地址。固件可以使用它来重用内存作为池。或者 RTOS 可能会使用它,以便它不会超过任务的内存限制。

这实际上是一个糟糕的例子,说明它是如何使用的。您永远不会新建一个数组,然后将新数组放入其中。您将有一个指向周围分配的内存块的指针,并且您将使用placement new 。

于 2021-06-04T23:57:13.777 回答