*新总是错的。总是

时间:2013-11-22 13:57:56

标签: c++

为了解释指针和引用in this question,我编写了这段代码。

MyClass& MyClass::MyInstance()
{       
    static MyClass & myLocalVariable = * new MyClass(/*parameters*/);
    return myLocalVariable ;
}

其中一条评论,通过一个令人印象深刻的高声誉SO用户,简单地指出: *新总是错的。 ALWAYS。

这是我第一次被告知:这是一个我们都应该知道的着名编码标准吗?背后的原因是什么?

5 个答案:

答案 0 :(得分:9)

我通常很务实,但这对我来说太过分了!

static MyClass & myLocalVariable = * new MyClass(/*parameters*/);

真的?为什么不简单:

static MyClass myLocalVariable{/*parameters*/};

答案 1 :(得分:3)

最明显的原因是,如果你没有保留新返回的指针的副本,你就不可能在其上调用delete。

在更人性化的层面上,它会让人们在阅读你的代码时更少考虑你,这也不是一件好事。

答案 2 :(得分:0)

我相信声明的用户意味着使用new分配静态对象是危险的,因为内存最有可能被泄露。更重要的是,您的变量不是指针而是引用,因此您永远不会释放new返回的内存的可能性更大(您多久删除一次引用的地址?)。

答案 3 :(得分:0)

问题不仅仅是无用的分配。

如果没有人对其进行删除,则不会删除。当然,程序结束时会释放内存但是它的析构函数不会被调用。

比较以下代码中使用Get()Get2()的输出:

    #include <iostream>

    struct A
    {
        ~A(){std::cout << "Deleted\n";}
    };

    A& Get()
    {
      static A & a = *new A;
      return a;
    }

    A& Get2()
    {
      static A a;
      return a;
    }

    int main()
    {
       //Case 1
       Get();
       //Case 2
       Get2();
    }

调用Get时调用DeletedGet2时,此程序的输出无效。
换句话说,在案例1中,在程序终止时,具有非平凡析构函数的资源(例如,提交关闭文件句柄)将不会被正确销毁,但在案例2中将会被销毁。

答案 4 :(得分:0)

问题是raw new不指定所有权。如果我新建一个物体并将其归还,谁拥有它?创建函数/对象是拥有它还是调用函数?如果返回智能指针(std :: shared_ptr和std :: unique_ptr),则指定所有权。

不指定所有权是泄漏内存的最简单方法之一。即使是专业的程序员,我也是最艰难的时刻,让人们了解所有权并使用它。这主要是通过使用指定所有权的良好类型(智能指针)来阻止的,只是通过现有的。

type* function();    // Unspecified ownership.
                     // Must be well documented and all users must read
                     // and follow the documentation.
std::unique_ptr<type> function(); // Calling function owns returned pointer.
                                  // Single ownership.
std::shared_ptr<type> function(); // Calling function owns returned pointer.
                                  // Shared ownership.  Can have multiple owners.
std::weak_ptr<type> function();   // Calling function references returned pointer.
                                  // Must lock pointer to get owned object, if not deleted.
                                  // Shared ownership.  Can have multiple owners.

这些不同类型的指针仅通过现有的指针表示所有权。

至于new总是错的。这是一个过于笼统的概括。 std::shared_ptr是使用全局函数std::make_shared创建的。从C ++ 11开始,没有std::make_unique,但这将在C ++ 14中修复。创建std::unique_ptr的唯一方法是使用new和立即将指针指定给std::unique_ptr

还有一些地方你需要一个原始指针并手动使用newdelete,但它们往往是非常低级的,大多数程序员很少会遇到它们。


我真正感受到的是您的代码并不是因为您正在使用new,而是您正在取消引用指针并将其指定给引用。几乎不可能保证析构函数将被调用。它也倾向于泄漏内存,但是在分配给静态变量的情况下,它将在程序终止时解除分配,因此你并不真正关注内存泄漏。

MyClass& MyClass::MyInstance()
{       
    static MyClass & myLocalVariable = * new MyClass(/*parameters*/);
    return myLocalVariable ;
}

我更愿意创建静态变量,而不是通过引用。这可以防止将对象放在堆上。根据{{​​1}},还可以允许对象从可执行文件映射到内存,而无需运行任何代码来初始化它。

MyClass