【问题标题】:What does "new (&variable) value;" in C++ do?“新(&变量)价值”是什么?在 C++ 中做什么?
【发布时间】:2012-11-17 13:52:18
【问题描述】:

假设我在 C++ 程序中有以下代码:

Object a = Object(someParameters);
new (&a) Object(someOtherParameters);

我的假设是它将a 的内容替换为Object(someOtherParameters),避免为Object 声明可能的operator=。这是正确的吗?

【问题讨论】:

  • 作为现有答案的旁白:您问题的 title 中的语法不存在!您不能将此语法与任何值一起使用,您可以在构造函数调用中使用它——即value 必须采用T(arguments) 的形式。
  • 放置 new 总是在 C++ 内存池(对象池)中使用。作为附加回复。

标签: c++ operators new-operator


【解决方案1】:

它叫做placement new。它在指定内存上调用构造函数,而不是分配新内存。请注意,在这种情况下,您必须在释放分配的内存之前显式调用对象的析构函数。

澄清。假设你分配了一些原始内存

char * rawMemory = new char [sizeof (Object)];

并且您想在该内存上构造一个对象。你打电话

new(rawMemory) Object(params);

现在,在释放内存之前

delete [] rawMemory; 

你必须显式调用 Object 的 derstuctor

reinterpret_cast<Object*>(rawMemory)->~Object();

但是,在您的特定示例中,潜在的问题是您没有正确销毁现有对象,然后再在其内存中构造一个新对象。

奖励: 有没有想过标准std::vector 在其包含的对象不被默认构造的情况下如何做到?原因是大多数(如果不是全部)实现allocator&lt;T&gt; 不存储T* p,这将要求T 在p = new T[N] 的情况下是默认可构造的。相反,它存储 char 指针 - 原始内存,并分配 p = new char[N*sizeof(T)]。当您 push_back 一个对象时,它只是调用复制构造函数,并将 new 放置在该 char 数组中的适当地址上。

【讨论】:

  • 最后一句话令人困惑/错误:在释放对象内存之前,析构函数在作用域结束时自动调用。但是必须在覆盖之前调用 previously existing 对象的析构函数。为了更好,这个答案还应该提到重载运算符的可能性——重载可能会做一些完全不同的事情。
  • @KonradRudolph:不,不是。 Class* object = new (rawMemory) Class(params); 以后不能再调用delete object;,因为正常new 没有分配内存。因此,您必须在调用delete [] rawMemory 之前显式调用object-&gt;~Class()
  • OP 问题中的对象是堆栈分配的并且类型正确,因此您的反对意见不适用。即使对于动态分配的内存,您也可以很好地执行以下操作:T* x = new T; x-&gt;~T(); new (x) T(); delete x;(注意析构函数调用和放置 new 的顺序!)
  • 答案和 Konrad 的评论都未能解决如果程序不依赖于副作用,不调用析构函数是完全可以的(根据标准,祝代码审查好运)析构函数,对于调用放置 new 之前的旧对象和新对象。
  • Bonus 部分*错误*/不精确。大多数实现确实持有T*,尽管不是用new T[] 获得的。容器跟踪T* 分配和指向的内存有多少对应于实际的T 对象以及有多少未初始化。
【解决方案2】:

它被称为placement new:它在括号内给定的地址处构造新的Object。放置 new 通常用于在原始内存中创建对象。像这段代码那样在现有对象之上构造一个新对象是个坏主意,因为它不会调用原始对象的析构函数。

【讨论】:

    猜你喜欢
    • 2012-03-05
    • 2017-09-12
    • 2011-01-11
    • 1970-01-01
    • 2022-01-17
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    相关资源
    最近更新 更多