16

为了避免继续使用->并直接使用对象,是否可以接受以下做法:

obj x = *(new obj(...));
...
delete &obj;
4

4 回答 4

31

这不仅是糟糕的做法,而且:

  1. 内存泄漏(很可能,除非您使用的模式在您提供的代码中不可见),因为obj将存储由表达式创建的原始对象的副本new,并且返回的指向该对象的指针new丢失;
  2. 最重要的是,未定义的行为,因为您正在传递delete一个指向未分配的对象的指针new。根据 C++11 标准的第 5.3.5/2 段:

[...] 在第一种选择(删除对象)中,delete 的操作数的值可以是空指针值、指向由先前的new-expression创建的非数组对象的指针或指向子对象的指针(1.8) 表示此类对象的基类(第 10 条)。如果不是,则行为未定义

于 2013-05-13T17:34:01.360 回答
9

不,事实上这会导致泄漏。x复制初始化的,所以指向的原始对象new obj丢失了。

只需使用

obj x(...);

无需动态分配。或者

obj x = obj(...);

如果你必须(怀疑)。

于 2013-05-13T17:33:51.120 回答
7

当然不是;将动态对象复制到自动变量,丢失指向它的唯一指针,然后尝试删除自动副本。您有内存泄漏和无效删除。

首先使用自动变量会更好:

obj x(...);
...
// no need to delete anything

或者,如果由于某种原因它确实必须是动态的(因为它对于堆栈来说太大了,或者你并不总是想在这里销毁它),然后使用智能指针,如果你真的不喜欢,请使用引用->

std::unique_ptr<obj> p(new obj(...));
obj & x = *p;
...
// still no need to delete anything

将您的更改x为引用将是有效的(只要您注意异常、早期函数返回等不会导致泄漏),但会在不幸不得不维护它的任何人之间引起混乱。

于 2013-05-13T17:37:11.220 回答
0

如果您这样做,您将无法正确删除您的对象。

隐式地执行以下操作。

class A
{
public:
  int test (void) { return 1; }
};

int main (void)
{
  A * p = new A;
  A v(*p);
  //...
  delete &v; // &v != p and v is not constructed via new!
  return 0;
}

如果您想使用类似对象的语法,您可以绑定对该对象的引用。

class A
{
public:
  int test (void) { return 1; }
};

int main (void)
{
   A * p = new A;
   A & r = *p;
   int i = r.test();
   delete p;
   return 0;
}

如果你通过同一个指针删除你的对象,就不会有泄漏。

于 2013-05-13T17:40:43.947 回答