解除“新”指针被认为是好的风格吗?

时间:2013-05-13 17:32:28

标签: c++ pointers new-operator dereference

为了避免继续使用->而是直接使用该对象,可以接受的做法是:

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

4 个答案:

答案 0 :(得分:29)

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

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

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

答案 1 :(得分:9)

不,实际上这会导致泄漏。 x 复制初始化,因此new obj指向的原始对象将丢失。

只需使用

obj x(...);

无需动态分配。或

obj x = obj(...);

如果你必须(怀疑)。

答案 2 :(得分: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更改为引用将是有效的(只要您小心异常,早期函数返回等不会导致泄漏),但会导致任何不幸的人之间的混乱足以维持它。

答案 3 :(得分: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;
}

如果通过同一指针删除对象,则不会发生泄漏。

相关问题