C++ 在C+中,是否在特定情况下创建对象而不删除新运算符+;

C++ 在C+中,是否在特定情况下创建对象而不删除新运算符+;,c++,object,new-operator,C++,Object,New Operator,如果我们有以下代码段: MyObject my_object = MyObject(0); my_object = MyObject(1); MyObject(0)会发生什么情况?它被删除了吗?看看我读到的关于它的内容,只有当我们离开创建范围时,它才应该被删除,所以anwser可能是no。如果是这种情况,除了使用指针之外,还有什么方法可以显式删除它吗?第1行正在创建一个临时对象,这个对象被分配给我的_对象。 在第二行中,将创建一个临时对象,并将其指定给my_对象 所以只有一个对象,我的对象 我

如果我们有以下代码段:

MyObject my_object = MyObject(0);
my_object = MyObject(1);

MyObject(0)会发生什么情况?它被删除了吗?看看我读到的关于它的内容,只有当我们离开创建范围时,它才应该被删除,所以anwser可能是no。如果是这种情况,除了使用指针之外,还有什么方法可以显式删除它吗?

第1行正在创建一个临时对象,这个对象被分配给我的_对象。 在第二行中,将创建一个临时对象,并将其指定给my_对象

所以只有一个对象,我的对象

我们不需要考虑临时对象。编译器负责处理临时对象

MyObject my_object = MyObject(0);
此行使用
MyObject
的构造函数在堆栈上创建
myu对象
,该构造函数可以接受
int

my_object = MyObject(1);
这一行再次使用与第一行相同的构造函数创建临时MyObject。然后,通过调用赋值操作符,将其赋值给
my_object
。如果您没有提供此运算符,那么编译器将为您创建一个执行浅复制的运算符。当该语句完成时,临时MyObject将超出范围,并调用其析构函数


当您的
my_对象
超出范围时,它将以同样的方式被销毁。在任何时候,都不需要手动删除这个文件,因为所有的东西都是在堆栈上分配的。

< P> >代码>删除>代码>在C++中有特殊的含义,所以删除的使用是不吉利的。
MyObject my_object = MyObject(0);
此行声明使用自动存储持续时间(即,在堆栈上)创建类型为
MyObject
的对象。当作用域结束时,此对象将被析构函数(即,将执行其析构函数)。本标准中未对相关存储器的回忆作出规定(见后面的示例)

此类型为
MyObject
的对象将使用表达式
MyObject(0)
构造。此构造函数将初始化为独占使用而设置的内存

注意:实际上,可以创建一个临时函数,然后调用复制构造函数,但谢天谢地,大多数编译器避开了这个中间步骤,因为标准特别允许它

此行将一个由表达式
MyObject(1)
确定的新值分配给已存在的
myu对象。为此,将创建一个具有自动存储持续时间的
MyObject
临时类型。然后,执行赋值运算符;如果没有重载,它会将临时对象的状态复制到
my_对象中
,擦除先前的状态。在表达式的末尾,临时性被销毁(同样,没有为相关内存的回忆做任何准备)

注意:
MyObject(0)
不会被“删除”,因为它不存在,相反,它将状态写入的内存会被重新使用以从
MyObject(1)
复制状态


正如所承诺的,既然这似乎是你的担忧,那么就讨论一下记忆方面。这是特定于编译器的,但大多数编译器的行为都类似

假设我们有以下函数:

void f() {
  MyObject my_object = MyObject(0);

  {
    my_object = MyObject(1);
    do_something(my_object);
  }

  {
    my_object = MyObject(2);
    do_something(my_object);
  }
}
堆栈上需要多少空间

  • 我们假设它在第一行执行直接构造
  • 我们假设编译器没有足够的智能来执行堆栈着色(例如,Clang没有)
根据这些假设,它需要3
MyObject
的空间

  • MyObject my_object=MyObject(0)
    my_对象
    需要一直运行到函数结束
  • my_object=MyObject(1):创建临时需要
  • my_object=MyObject(2):创建临时需要
在函数执行结束时重新收集堆栈空间

如果编译器足够聪明,可以执行堆栈着色,那么这两个临时对象(从不需要在一起)可以使用相同的内存点,从而将空间需求降低到2
MyObject

智能优化器也可能直接将
MyObject(1)
MyObject(2)
直接构建到
myu对象中(如果它可以证明效果与构建临时对象然后复制它相同),从而将空间需求降低到1
MyObject

最后,如果
do\u something
的定义是可见的,并且它没有使用其参数,那么在某些条件下,它(理论上)可以完全绕过
my\u对象的构造。这种优化可以通过以下简单的程序实现:

int main() { int i = 0; for (; i < 1000; ++i); return i; }
(注意
i
是如何消失的)


正如你可能注意到的。。。实际上很难猜测编译器/优化器能够做什么。如果你真的有很紧的内存需求,那么(也许令人惊讶的是),你最好的选择可能是用函数替换块。

当谈论新创建的对象时,内存中有两个主要区域:堆栈和堆。堆包含使用new动态创建的所有对象。需要使用delete操作符显式删除这些对象。堆栈是范围特定的,堆栈上定义的所有对象都将自动删除。由于不使用new,因此当对象的作用域结束时,所有对象都将被销毁

假设没有编译器优化,您的代码大致可以转换为:

{
   MyObject my_object;
   MyObject tempObject0(0);
   my_Object = tempObject0;
   MyObject tempObject1(1);
   my_Object = tempObject;
}//3 objects are deleted by this point (in theory)
还要注意

MyObject myObject(0);


第二种情况创建一个临时对象,因此效率较低。这当然是假设没有优化。根据编译器的不同,它可能会转换为相同的内容。

好的,听起来不错,那么编译器是否真的要删除它呢?我不希望内存泄漏?如果从堆中分配的内存未被释放,则会发生内存泄漏。这里,临时对象的内存是从堆栈中分配的。所以你不必担心内存泄漏,所以我是
{
   MyObject my_object;
   MyObject tempObject0(0);
   my_Object = tempObject0;
   MyObject tempObject1(1);
   my_Object = tempObject;
}//3 objects are deleted by this point (in theory)
MyObject myObject(0);
MyObject myObject = MyObject(0);