C++ 可以给新放置指定堆栈对象地址吗?

C++ 可以给新放置指定堆栈对象地址吗?,c++,stack,new-operator,heap-memory,placement-new,C++,Stack,New Operator,Heap Memory,Placement New,忽视这种做法的有用性。(当然,尽管现实生活中的例子很受欢迎。) 例如,以下程序为a输出正确的值: #include <iostream> using namespace std; int main() { int a = 11111; int i = 30; int* pi = new (&i) int(); cout << a << " " << endl; } #包括 使用名称空间std; int main()

忽视这种做法的有用性。(当然,尽管现实生活中的例子很受欢迎。)

例如,以下程序为
a
输出正确的值:

#include <iostream>

using namespace std;

int main()
{
  int a = 11111;
  int i = 30;

  int* pi = new (&i) int();

  cout << a << " " << endl;
}
#包括
使用名称空间std;
int main()
{
INTA=11111;
int i=30;
int*pi=new(&i)int();

cout是的,使用指向堆栈上某个对象的指针执行placement new完全可以。它将仅使用该特定指针在中构造该对象。placement new实际上并不分配任何内存-您已经提供了该部分。它只执行构造。随后的删除将不起作用通常是
delete
——因为您需要做的就是调用对象的析构函数。实际内存由其他东西管理——在本例中是堆栈对象

例如,对于这种简单类型:

struct A {
    A(int i) 
    : i(i)
    {
        std::cout << "make an A\n";
    }

    ~A() {
        std::cout << "delete an A\n";
    }

    int i;
};

安置新的建筑,而不是分配,所以没有簿记信息可怕

目前,我可以想到一个可能的用例,尽管它(以这种形式)是封装的一个不好的例子:

#include <iostream>
using namespace std;
struct Thing {
 Thing (int value) {
  cout << "such an awesome " << value << endl;
 }
};
union Union {
 Union (){}
 Thing thing;
};
int main (int, char **) {
 Union u;
 bool yes;
 cin >> yes;
 if (yes) {
  new (&(u.thing)) Thing(42);
 }
 return 0;
}
#包括
使用名称空间std;
结构物{
事物(int值){

coutPlacement new在适当的位置构造元素,不分配内存

本例中的“簿记信息”是返回的指针,应该用来销毁放置的对象

由于放置是一个构造,因此没有与放置关联的删除。因此,放置新位置所需的“清理”操作是销毁

“通常的步骤”是

  • “分配”内存
  • 在适当位置构造元素
  • 做事
  • 销毁元素(与2相反)
  • “解除分配”内存(与1相反)
  • (其中内存可以是堆栈内存,它不需要显式分配也不需要释放,而是随堆栈数组或对象来来去去。)

    注意:如果将一个对象“放置”到堆栈上相同类型的内存中,应该记住在对象的生命周期结束时会自动销毁

    { 
      X a;
      a.~X(); // destroy a
      X * b = new (&a) X(); // Place new X
      b->~X(); // destroy b
    } // double destruction
    

    不,因为您不
    删除
    已更新位置的对象,所以可以手动调用其析构函数

    struct A {
        A() { std::cout << "A()\n"; }
        ~A() { std::cout << "~A()\n"; }
    };
    
    int main()
    {
        alignas(A) char storage[sizeof(A)];
    
        A *a = new (storage) A;
        std::cout << "hi!\n";
    
        a->~A();
        std::cout << "bye!\n";
    }
    
    在您的例子中,也不需要调用析构函数,因为
    int
    是可平凡地析构函数,这意味着它的析构函数无论如何都是不可操作的


    但请注意,不要在仍处于活动状态的对象上调用placement new,因为不仅会破坏其状态,而且还会调用其析构函数两次(手动调用时调用一次,也会在原始对象应该被删除时调用一次,例如在其作用域的末尾).

    按照这种逻辑,新的位置总是会被破坏/不可能的。你没有做任何分配…@LightnessRacesinOrbit你是什么意思?正是我说的。它的析构函数可能是不可操作的,但如果你调用析构函数并让它超出范围(你无法避免),它会被调用两次.传统上,新位置会出现在
    char[]
    (正如您在回答中所做的那样)中,而不是出现在
    int
    (如问题中的OP所做的那样).@LightnessRacesinOrbit哦,我在我的示例中搜索。注意:添加了,谢谢!当我在最后一行尝试您的示例时,正如您所示。这是一个gcc错误还是代码中隐藏着未定义的行为?
    { 
      X a;
      a.~X(); // destroy a
      X * b = new (&a) X(); // Place new X
      b->~X(); // destroy b
    } // double destruction
    
    struct A {
        A() { std::cout << "A()\n"; }
        ~A() { std::cout << "~A()\n"; }
    };
    
    int main()
    {
        alignas(A) char storage[sizeof(A)];
    
        A *a = new (storage) A;
        std::cout << "hi!\n";
    
        a->~A();
        std::cout << "bye!\n";
    }
    
    A()
    hi!
    ~A()
    bye!