你会如何替换'new'关键字?

时间:2009-08-13 07:03:35

标签: c++ language-design new-operator keyword

很久以前我发现了一篇文章(我找不到ATM),它说明了为什么C ++中的新关键字不好的原因。我无法记住所有的原因,但我最记得的两个是你必须将new与delete,new []和delete []匹配,你不能像使用malloc一样使用#define。

我正在设计一种语言,所以我想问你如何改变C ++语言,这样新的更友好。随意陈述新的和文章的问题。我希望我能找到文章链接,但我记得它很长,是由(IIRC)一所知名学校的教授写的。

8 个答案:

答案 0 :(得分:6)

我看不出有任何理由用其他东西替换new关键字(似乎是C ++委员会同意我的意见)。它很清楚并且应该做到。您可以在班级中覆盖operator new,无需使用定义。

要消除new[] / delete[]问题,您可以使用std::vector

如果你想使用智能指针你可以使用它,但我想控制何时使用智能指针。这就是为什么我喜欢它在C ++中的工作原理 - 能够控制低级细节的高级行为。

答案 1 :(得分:3)

问题匹配new,delete,new [],delete []

没什么大不了的 你应该在一个类中包装内存分配,这样就不会影响普通用户。单个obejct可以用智能指针包裹。虽然数组可以用std :: Vector<>

表示

不能像使用malloc一样使用#define。

像这样搞乱malloc的原因是在你的应用程序和标准内存管理层之间引入你自己的内存管理层。这是因为在C中你不允许编写自己的malloc版本。在C ++中编写自己的新版本是非常合法的,这使得这个技巧变得不必要。

答案 2 :(得分:2)

我会在C#(或多或少)中给它new的语义:

  1. 为对象分配内存。
  2. 通过将成员变量设置为默认值来初始化内存(对于值,通常为0,对于引用,通常为null。)
  3. 初始化对象的动态绑定机制(C ++中的vtables,为托管VM键入def表)。
  4. 调用构造函数,此时虚拟调用按预期工作。
  5. 对于没有垃圾收集的语言(此时用于新语言),请从通话中返回smart_ptr或类似内容。
  6. 此外,使所有对象都是值类型或引用类型,因此您不必保持显式smart_ptr。只允许new为引用类型堆分配,并确保它包含正确调用析构函数的信息。对于值类型,new从堆栈调用内存中的构造函数。

答案 3 :(得分:1)

使用垃圾收集,以便您永远不需要将new与任何内容匹配。

答案 4 :(得分:1)

通过使用STL容器类和各种boost:smart_ptrs,几乎不需要在C ++代码中显式调用new或delete。

您可能需要调用new的几个地方(例如,初始化智能指针)使用Named Constructor Idiom返回包含在其中的类类型指针,例如 a boost:shared_ptr

但是C ++和STL非常努力地允许你将大多数对象视为值对象,因此你可以构造对象而不是指针而只是使用它们。

鉴于这一切,几乎没有必要更换新的运算符 - 这样做会引入许多问题,无论是需要垃圾收集器,还是通过减少C ++为程序员提供的精细低级控制。

答案 5 :(得分:0)

如果您的语言是垃圾回收,则可以避开关键字。这就是Python所做的事情(和Lisp几乎在五十年前所做的一样!)。另请参阅Peter Norvig提供的类似问题的答案here。 (没有“新闻”好消息吗?)

答案 6 :(得分:0)

有时您想要用工厂替换构造函数。这是一个众所周知的重构。 Replace Constructor With Factory Method。那么也许这就是文章的意思?

顺便提一下,您经常会看到用Factory Method替换新的直接来电。

DI Unity这样的DI框架将这个概念带到了另一个层面。正如您在以下C#代码中看到的,没有应用“new”来创建IMyClass接口:

IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<IMyClass, SomeClass>();
IMyClass thing = myContainer.Resolve<IMyClass>();

答案 7 :(得分:0)

C ++具有单独的new运算符(或C malloc)的原因主要是为了创建对象的生命周期超出创建它们的函数的范围。

如果你有尾部调用消除和延续,你可能不关心 - 对象可以全部在堆栈上创建并具有无限范围 - 一个对象可以存在,直到你调用对应于超出范围的对象的延续并被毁坏。然后你可能需要一些东西来垃圾收集或以其他方式压缩堆栈,这样它就不会充满不再需要的对象(Chicken Scheme和TinyOS 2是两个不同的例子,用于在运行时或动态内存中提供动态内存的效果。编译时;鸡计划不允许RAII和TinyOS不允许真正的动态分配),但是对于大量的代码,这样的方案与RAII没有太大的不同,可以选择更改订单物体被毁坏了。