Possible Duplicate:
In C++, why should new be used as little as possible?
在C++中实例化一个类,使用"新"真的是个坏主意吗?在这里找到的。
我知道使用原始指针是不明智的,但是为什么在这样糟糕的实践中使用"new"关键字呢?或者是?
- 通常不需要使用值语义的new类型。我想这就是杰瑞所说的。
- 投票结束。这应该是一个有关链接问题的评论线索,因为这个问题是基于对答案的根本性误解!一般来说,new并不是一个坏主意。您链接的答案建议删除new()以解决编译时错误:不能将指针传递给不需要的函数!
- 如果你去掉了C++中的"原始指针",你就不会有太多的东西了。
- 过去15年的C++库开发一直致力于寻找避免使用新方法的方法。显式内存管理很难纠正。
- @Hanspassant:我认为更重要的是,编写正确的手动分配的困难在于自动和手动生命周期之间的根本区别,而且所有程序逻辑中绝大多数都是由自动对象提供的,而不是由手动对象提供的(这要归功于巧妙的库构建,在很大程度上是由智能对象提供的)。块)。顺便说一句,投票重新打开,因为链接的问题似乎有点不同(答案过于注重实现细节,而不是更相关的语言语义)。
- @凯瑞克-好吧,我没有意见。垃圾收集器现在非常流行,这只是将内存管理留给库的另一个方面。C++的角度是,当需要时,可以打破库依赖关系。即使每个人都告诉你不要这样做。这是来自[C++]标签频率的奇怪建议。几乎听上去他们以前从未使用过GC。让我们闭嘴吧,太主观了。
关键是,new与怀孕很像,它创建了一个由人工(即由您)管理的资源,因此它是有责任的。
C++是一种用于图书馆写作的语言,无论何时你看到一种责任,"C++"的方法是编写一个处理这个的库元素,并且仅仅是这个,责任。对于动态内存分配,这些库组件已经存在,概括地称为"智能指针";您将要查看std::unique_ptr和std::shared_ptr(或它们的tr1或boost等价物)。
在编写这些单一责任构建块时,您确实需要说new和delete。但是一旦这样做了,您就要仔细考虑,确保提供正确的复制、分配和破坏语义。(从例外安全的角度来看,单一责任是至关重要的,因为一次处理多个单一资源是不可分割的。)
一旦你把所有的东西都分解成合适的构建块,你就可以把这些块组合成越来越大的代码系统,但是在这一点上,你不再需要执行任何手动的职责,因为构建块已经为你做了这件事。
由于标准库为绝大多数用例(动态数组、智能指针、文件句柄、字符串)提供了资源管理类,关键在于一个经过精心设计和精心制作的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++很少需要动态存储"。我觉得这可能是手术问题的一部分。这个问题的措词可能更恰当:"动态分配对象真的是个坏主意吗?".只有在您确定您确实需要动态存储之后,我们才能适当地讨论您是否应该说很多new和delete,或者是否有更好的选择,这是我最初的答案。
- + 1比较EDCOX1与0的无保护性行为,这有助于解释为什么C++聊天室倾向于经常讨论这个问题。
- +第一段为1。其余的我没读。这是个好职位吗?
- 这似乎是一个深思熟虑和完整的解释。谢谢你的澄清
- "从另一种面向对象语言进入C++时,最重要的事情是,大多数对象只需要有自动的生命周期,因此就没有什么可担心的。"我同意"大多数"。如果您正在编写一个库或引擎-我可以想象一个延长对象寿命的好用例。有人可能会说,你可以只返回一个对象的副本-但我真的认为这是浪费。
- "C++是图书馆写作的一种语言"对我来说有点奇怪。这可能很好,但这并不意味着就是为了这个。当然,C++的原创性故事并没有给我读到这样的目的,我以前没有听过这个具体的说法。你能详细解释一下你所说的意思吗?
尽可能避免new意味着许多好处,例如:
首先,你也要避免使用delete语句,尽管聪明的指针可以帮助你。所以这不是重点。
你可以避免三的规则(C++ 03),或者五的规则(C++ 11)。如果在设计类时使用new,也就是说,当您的类在内部管理原始内存时,您可能需要考虑这个规则。
当不使用new时,很容易实现异常安全代码。否则,您将面临许多难题,使您的代码异常安全。
不必要地使用new意味着你会招来麻烦。我见过,当一个没有经验的程序员使用new时,他通常有更好的选择,例如使用标准容器和算法。使用标准容器可以避免使用new时出现的大多数问题。
- 在设计一个类时必须考虑三/五的规则,而不是在决定如何使用它时。另外两个是正确的。
- @斯比:我知道,这就是为什么我说"你可能要考虑这个规则"。
- @斯比:我现在在回答中说得很清楚了。
- 我想现在我明白了:你的意思是当你没有new类数据成员时??
- @斯比:老实说,我不明白你的问题(我的回答是指哪一部分?).
- 关于trot/f的。当我设计一个类时,我需要决定实现复制/移动,不管类中的对象是动态创建的还是自动创建的。如果您不是指设计的类的用法,而是指动态创建的类中的数据成员,那么您是对的。只是从你的回答中看不清楚。
- @SBI:事实上,如果你注意到了,我已经编辑了我的答案,明确地说我正在讨论设计一个类本身,它内部管理内存。
这并不坏,但是你用new分配的所有东西都必须用delete处理。这并不总是琐碎的事情,特别是当你考虑到异常的时候。我想这就是那篇文章的意思。
- 你用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。
- 删除关键字(a la objective-c)并不能消除概念。
- @丹尼尔是的,我的回答也这么说。
这取决于代码需要什么。它是您引用的回复,向量包含客户机实例,而不是指向客户机实例的指针。
在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.
} |
- 显示基于指针的方法,抱怨它们不会在函数末尾破坏对象,然后使用shared_ptr将其添加回去,这有什么意义?为什么不像原来的V1那样按值存储对象呢?如果您不需要它们超过当前范围,那么将它们进行动态分配是没有意义的,而这并不是。
new你的delete和free你的malloc什么(不要混用,你会惹麻烦的)。有时您必须使用new,因为用new分配的数据不会超出范围…除非数据指针丢失,这是new的全部问题。但这是程序员的错误,而不是关键字。
- 在C++中不要使用MALLC。
- @Catplusplus:…除非你想或需要:—)(看着你,malloc分配器。)
- "有时您必须使用新的,因为与新分配的数据不会超出范围…"通常有更好的方法来解决这个问题,例如使用std::shared_ptr或其他资源管理、所有权共享类,这些类仍然处理所有丑陋的细节,如new或delete,并避免用户必须获得所有权利(a从统计学上讲,不可避免地会忘记这样做)。
这不是一个"坏主意,使用新的"--海报错误地陈述了他的情况相当严重。相反,使用新的而不是给你两个不同的东西。
new为您提供了一个新的、单独分配的类实例,并返回指向该实例的指针。
使用不带new的类名创建类的自动实例,当类超出作用域时,该实例将变为"poof"。这将"返回"实例本身,而不是指针(从而返回另一个线程中的语法错误)。
如果在引用的情况下使用new并添加*来传递编译器,则会导致对象泄漏。另一方面,如果您将一个参数传递给一个将要在某个地方存储它的方法,并且传递了一个未更新的实例,使它与&一起工作,那么您将得到一个存储的悬空指针。
- 事实上,我不认为杰瑞说的是错的,但我认为wtfsven理解得很差。这是对一个特定问题的回答,这个回答是对的,imnsho。我同意,一般情况下,你应该尽可能避免使用new/delete。
- 我的意思是,他根本无法解释为什么会这样——他基本上只是说,"如果你能避免的话,就不要用新的",这甚至不能解释这些区别。
- @但丹尼尔解释说,普遍是相当不平凡的,并不真正属于另一个答案。它属于这里。;-)
- 那你为什么不发表解释呢?;)