Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 取消引用'new'指针被认为是好的风格吗?_C++_Pointers_New Operator_Dereference - Fatal编程技术网

C++ 取消引用'new'指针被认为是好的风格吗?

C++ 取消引用'new'指针被认为是好的风格吗?,c++,pointers,new-operator,dereference,C++,Pointers,New Operator,Dereference,为避免继续使用->,而直接使用对象,可接受的做法是: obj x = *(new obj(...)); ... delete &obj; 不,事实上这导致了泄漏x已复制初始化,因此由新obj指向的原始对象丢失 只用 obj x(...); 不需要动态分配。或 obj x = obj(...); 如果你必须(怀疑它)。这不仅是糟糕的做法,而且: 内存泄漏(最有可能的情况是,除非您使用的模式在您提供的代码中不可见),因为obj将存储由new表达式创建的原始对象的副本,并且new返回的指

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

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

不,事实上这导致了泄漏
x
复制初始化,因此由
新obj
指向的原始对象丢失

只用

obj x(...);
不需要动态分配。或

obj x = obj(...);

如果你必须(怀疑它)。

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

  • 内存泄漏(最有可能的情况是,除非您使用的模式在您提供的代码中不可见),因为
    obj
    将存储由
    new
    表达式创建的原始对象的副本,并且
    new
    返回的指向该对象的指针丢失
  • 最重要的是,未定义的行为,因为您正在向
    delete
    传递指向未分配
    new
    的对象的指针。根据C++11标准第5.3.5/2段:
  • […]在第一个备选方案(delete对象)中,delete操作数的值可以是空指针 值、指向由以前的新表达式创建的非数组对象的指针或指向子对象的指针(1.8) 表示此类对象的基类(第10条)如果不是,则行为未定义


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

    最好首先使用自动变量:

    obj x(...);
    ...
    // no need to delete anything
    
    或者,如果出于某种原因它确实必须是动态的(因为它对于堆栈来说太大了,或者您并不总是想在这里破坏它),那么使用智能指针,如果您确实不喜欢
    ->

    std::unique_ptr<obj> p(new obj(...));
    obj & x = *p;
    ...
    // still no need to delete anything
    
    std::unique_ptr p(新obj(…);
    obj&x=*p;
    ...
    //仍然不需要删除任何内容
    

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

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

    隐式地执行以下操作

    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;
    }
    

    如果通过同一个指针删除对象,则不会出现泄漏。

    第二个指针优于第一个指针。他不会泄漏内存,因为程序可能不会运行足够长的时间,他无法执行多个分配。嗯,至少可以执行
    obj&x=*new
    。或者您可以使用参考
    obj&=(*新…
    @Marcin你可以,但为什么?@Marcin是的,你可以。你也可以把键盘砸到屏幕上。仅仅因为你可以,并不意味着你应该。:@JamesKanze,因为OP想避免一直取消引用,这就是引用的目的。@Marcin如果你听从Luchian的建议,你就不必取消引用。