关于c ++:为什么使用’new’是个坏主意?


Why is it a bad idea to use 'new'?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
In C++, why should new be used as little as possible?

在C++中实例化一个类,使用"新"真的是个坏主意吗?在这里找到的。

我知道使用原始指针是不明智的,但是为什么在这样糟糕的实践中使用"new"关键字呢?或者是?


关键是,new与怀孕很像,它创建了一个由人工(即由您)管理的资源,因此它是有责任的。

C++是一种用于图书馆写作的语言,无论何时你看到一种责任,"C++"的方法是编写一个处理这个的库元素,并且仅仅是这个,责任。对于动态内存分配,这些库组件已经存在,概括地称为"智能指针";您将要查看std::unique_ptrstd::shared_ptr(或它们的tr1或boost等价物)。

在编写这些单一责任构建块时,您确实需要说newdelete。但是一旦这样做了,您就要仔细考虑,确保提供正确的复制、分配和破坏语义。(从例外安全的角度来看,单一责任是至关重要的,因为一次处理多个单一资源是不可分割的。)

一旦你把所有的东西都分解成合适的构建块,你就可以把这些块组合成越来越大的代码系统,但是在这一点上,你不再需要执行任何手动的职责,因为构建块已经为你做了这件事。

由于标准库为绝大多数用例(动态数组、智能指针、文件句柄、字符串)提供了资源管理类,关键在于一个经过精心设计和精心制作的C++项目应该不需要任何类型的人工资源管理,其中包括使用EDCOX1(0)。您的所有处理程序对象要么是自动的(作用域),要么是其他类的成员,这些类的实例依次作用域或由某人管理。

考虑到这一点,您唯一应该说的是new是创建一个新的资源管理对象;尽管这并不总是必要的:

1
2
3
std::unique_ptr<Foo> p1(new Foo(1, 'a', -2.5));   // unique pointer
std::shared_ptr<Foo> p2(new Foo(1, 'a', -2.5));   // shared pointer
auto p3 = std::make_shared<Foo>(1, 'a', -2.5);    // equivalent to p2, but better

最新消息:我想我可能只解决了行动计划的一半问题。许多来自其他语言的人似乎认为任何对象都必须用new类型的表达式实例化。在接近C++时,这本身是一个非常无用的心态。

C++中的关键区别是对象生存期或"存储类"。这可以是:自动(作用域)、静态(永久)或动态(手动)之一。全局变量具有静态生存期。绝大多数变量(在本地范围内声明为Foo x;)都具有自动生存期。它仅用于动态存储,我们使用new表达式。当从另一种面向对象语言进入C++时,最重要的事情是,大多数对象只需要有自动的生命周期,因此根本没有什么可担心的。

因此,第一个实现应该是"C++很少需要动态存储"。我觉得这可能是手术问题的一部分。这个问题的措词可能更恰当:"动态分配对象真的是个坏主意吗?".只有在您确定您确实需要动态存储之后,我们才能适当地讨论您是否应该说很多newdelete,或者是否有更好的选择,这是我最初的答案。


尽可能避免new意味着许多好处,例如:

  • 首先,你也要避免使用delete语句,尽管聪明的指针可以帮助你。所以这不是重点。

  • 你可以避免三的规则(C++ 03),或者五的规则(C++ 11)。如果在设计类时使用new,也就是说,当您的类在内部管理原始内存时,您可能需要考虑这个规则。

  • 当不使用new时,很容易实现异常安全代码。否则,您将面临许多难题,使您的代码异常安全。

不必要地使用new意味着你会招来麻烦。我见过,当一个没有经验的程序员使用new时,他通常有更好的选择,例如使用标准容器和算法。使用标准容器可以避免使用new时出现的大多数问题。


这并不坏,但是你用new分配的所有东西都必须用delete处理。这并不总是琐碎的事情,特别是当你考虑到异常的时候。我想这就是那篇文章的意思。


Is it really a bad idea to use 'new' in instantiating a class in C++?

这通常是不好的,因为它不是必需的,而且当您不假惺惺地使用它时,代码变得容易得多。如果你不用它就可以逃走,那么就这样做。我编写了整个库,没有使用过new

I get that using raw pointers is ill-advised, but why have a 'new' keyword at all when it's such bad practice? Or is it?

这不是普遍的坏,只是大多数时候不必要。但也有一些时候是合适的,这就是为什么有这样一个关键词。也就是说,如果没有EDCOX1,0可以混淆两个概念:1。它分配内存,和2。它将内存初始化为对象。

您可以使用其他内存分配方法,然后使用构造函数调用("placement new")来分离这些进程。这实际上是通过分配器在整个地方完成的,比如标准库。

另一方面,客户机代码管理未初始化的内存很少有意义(读:never),因此不将这两个进程分离是有意义的。因此出现了new


这取决于代码需要什么。它是您引用的回复,向量包含客户机实例,而不是指向客户机实例的指针。

在C++中,可以直接在堆栈上创建对象,而不使用新的,如下面的代码中的V1和V2:

1
2
3
4
5
6
void someFct()
{
     std::vector<client> V1;
     //....
     std::vector<client*> V2;
}

使用v2时,必须使用新操作创建新的客户机实例,但当v2超出作用域时,不会释放(删除)客户机对象。没有垃圾收集器。在离开函数之前必须删除对象。

要自动删除创建的实例,可以使用std::shared_ptr。这使得代码的编写时间更长,但从长远来看维护起来更简单:

1
2
3
4
5
6
7
8
9
10
11
void someFct()
{
    typedef std::shared_ptr<client> client_ptr;
    typedef std::vector<client_ptr> client_array;
    client_array V2;

    V2.push_back(client_ptr(new client()));

    // The client instance are now automatically released when the function ends,
    // even if an exception is thrown.
}


new你的deletefree你的malloc什么(不要混用,你会惹麻烦的)。有时您必须使用new,因为用new分配的数据不会超出范围…除非数据指针丢失,这是new的全部问题。但这是程序员的错误,而不是关键字。


这不是一个"坏主意,使用新的"--海报错误地陈述了他的情况相当严重。相反,使用新的而不是给你两个不同的东西。

new为您提供了一个新的、单独分配的类实例,并返回指向该实例的指针。

使用不带new的类名创建类的自动实例,当类超出作用域时,该实例将变为"poof"。这将"返回"实例本身,而不是指针(从而返回另一个线程中的语法错误)。

如果在引用的情况下使用new并添加*来传递编译器,则会导致对象泄漏。另一方面,如果您将一个参数传递给一个将要在某个地方存储它的方法,并且传递了一个未更新的实例,使它与&一起工作,那么您将得到一个存储的悬空指针。