您将如何替换“新”? 关键词?
我很久以前发现了一篇文章(我在 ATM 上找不到它),其中阐述了 C++ 中 new 关键字不好的原因。 我不记得所有的原因,但我记得最清楚的两个是你必须将new与delete匹配,new[]与delete[]匹配,并且你不能像与malloc一样使用#define与new。
我正在设计一种语言,所以我想问你如何改变 C++ 语言,这样新的语言就更友好了。 请随意陈述新文章和文章的问题。 我希望我能找到该文章的链接,但我记得它很长,并且是由(IIRC)一所知名学校的一位教授撰写的。
There was an article i found long ago (i cant find it ATM) which states reasons why the new keyword in C++ is bad. I cant remember all of the reasons but the two i remember most is you must match new with delete, new[] with delete[] and you cannot use #define with new as you could with malloc.
I am designing a language so i like to ask how would you change the C++ language so new is more friendly. Feel free to state problems with new and articles. I wish i can find the article link but i remember it was long and was written by a professor at (IIRC) a known school.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
C++ 具有单独的 new 运算符(或 C malloc )的原因主要是为了可以创建其生命周期超出创建它们的函数范围的对象。
如果您有尾部调用消除和延续,您就不会关心 - 对象都可以在堆栈上创建并且具有无限的范围 - 对象可以存在,直到您调用与超出范围并被破坏的对象相对应的延续。 然后,您可能需要一些东西来进行垃圾收集或以其他方式压缩堆栈,以便它不会充满不再需要的对象(ChickenScheme 和 TinyOS 2 是两个不同的示例,它们在运行时或编译时;鸡方案不允许 RAII,TinyOS 不允许真正的动态分配),尽管对于大量代码,这样的方案与 RAII 没有太大不同,可以选择更改顺序物体被毁坏。
The reason that C++ has a separate
new
operator ( or Cmalloc
) is primarily so that objects can be created whose lifetimes exceed the scope of the function which creates them.If you had tail call elimination and continuations, you wouldn't care - the objects could all be created on the stack and have unlimited extent - an object can exist until you call the continuation that corresponds to the object going out of scope and being destructed. You might then need something to garbage collect or otherwise compress the stack so it doesn't become full of no-longer required objects ( Chicken Scheme and TinyOS 2 are two different examples for giving the effect of dynamic memory without dynamic memory at either runtime or compile time; Chicken Scheme doesn't allow for RAII and TinyOS doesn't allow for true dynamic allocation ), though for a large amount of code such a scheme wouldn't be vastly different to RAII with the facility to chose to change the order the objects are destructed.
问题匹配 new、delete、new[]、delete[]
并不是什么大问题。
您应该将内存分配包装在一个类中,这样这不会真正影响普通用户。 单个对象可以用智能指针包装。 虽然数组可以用 std::Vector<> 表示,但也可以用 std::Vector<> 来表示。
不能像使用 malloc 那样将 #define 与 new 一起使用。
像这样搞乱 malloc 的原因是在您的应用程序和标准内存管理层之间引入您自己的内存管理层。 这是因为在 C 中,不允许您编写自己的 malloc 版本。 在 C++ 中,编写自己的 new 版本是相当合法的,这使得这个技巧变得不必要。
Problem match new, delete, new[], delete[]
Not really a big deal.
You should be wrapping memory allocation inside a class so this does not really affect normal users. A single obejct can be wrapped with a smart pointer. While an array can be represented by std::Vector<>
cannot use #define with new as you could with malloc.
The reason to mess with malloc like this was to introduce your own memory management layer between your app and the standard memory management layer. This is because in C you were not allowed to write your own version of malloc. In C++ it is quite legal to write your own version of the new which makes this trick unnecessary.
我会给它 C# 中的
new
语义(或多或少):null
为引用)来初始化内存。smart_ptr
或类似的值。另外,将所有对象设置为值类型或引用类型,这样您就不必保留显式的
smart_ptr
。 只允许 new 为引用类型进行堆分配,并确保它包含正确调用析构函数的信息。 对于值类型,new
从堆栈中调用内存上的构造函数。I'd give it the semantics of
new
in C# (more or less):null
for references).smart_ptr
or similar from the call.Also, make all objects either value types or reference types, so you don't have to keep an explicit
smart_ptr
. Only allownew
to heap-allocate for reference types, and make sure it contains information to properly call the destructor. For value types,new
calls the constructor on memory from the stack.使用垃圾收集,这样您就不需要将新的与任何东西相匹配。
Use Garbage Collection so that you never need to match new with anything.
通过使用STL容器类和各种boost:smart_ptrs,几乎不需要在C++代码中显式调用new或delete。
您可能需要调用 new 的几个地方(例如,初始化智能指针)使用命名构造函数惯用法来返回包装在 例如
boost:shared_ptr.
但是 C++ 和 STL 非常努力地允许您将大多数对象视为值对象,因此您可以构造对象而不是指针并直接使用它们。
考虑到这一切,几乎没有必要替换 new 运算符——而且这样做会引入许多问题,无论是需要垃圾收集器,还是减少 C++ 为程序员提供的精细低级控制。
By using the STL container classes and the various boost:smart_ptrs, there's little need to ever explicitly call new or delete in your C++ code.
The few places you might need to call new (e.g, to initialize a smart pointer) use the Named Constructor Idiom to return your class type pointer wrapped in, e.g., a
boost:shared_ptr
.But C++ and the STL work very very hard to allow you to treat most objects as value objects, so you can construct objects rather than pointers and just use them.
Given all this, there's little need to replace the new operator -- and doing so would introduce a host of problems, whether by requiring a garbage collector, or by reducing the fine low-level control C++ offers programmers.
如果您的new语言被垃圾收集,您可以避免使用new关键字。 这就是 Python 所做的事情(而 Lisp 几乎 5 年前就这么做了!)。 另请参阅 此处 Peter Norvig 针对类似问题提供的答案。 (没有“消息”就是好消息吗?)
If your new language is garbage collected, you can avoid the new keyword. Thats what Python did (and Lisp did almost 5 decades ago!). Also see an answer provided by Peter Norvig for a similar question here. (Is no "news" good news?)
有时您想用工厂替换构造函数。 这是众所周知的重构。 用工厂方法替换构造函数。 那么也许这就是这篇文章的意思?
顺便说一句,您经常会看到对 new 的直接调用被替换为工厂方法。
Unity 等 DI 框架将这一概念提升到了另一个层次。 正如您在以下 C# 代码中所看到的,没有应用“new”来创建 IMyClass 接口:
Sometimes you want to replace the constructor with a factory. This is a well known refactoring. Replace Constructor With Factory Method. So perhaps this is what the article meant?
Incidentally you will often see straight calls to new being replaced with a Factory Method.
DI frameworks such as Unity take this concept to another level. As you can see in the following C# code, there is no "new" applied to create the IMyClass interface:
我看不出有任何理由用其他东西替换
new
关键字(并且 C++ 委员会似乎同意我的观点)。 它很清晰,并且做了它应该做的事情。 您可以在类中重写operator new
,无需使用定义。要消除
new[]
/delete[]
问题,您可以使用std::vector
。如果你想使用智能指针,你可以使用它,但我想控制何时使用智能指针。 这就是为什么我喜欢它在 C++ 中的工作方式 — 具有控制低级细节的能力的高级行为。
I cannot see any reason to replace the
new
keyword with something else (and seems to be that C++ committee agree with me). It is clear and makes what it should. You could overrideoperator new
in your class, no need to use defines.To eliminate
new[]
/delete[]
problem you could usestd::vector
.If you want to use smart pointer you could use it, but I want to control when smart pointer will be used. That's why I like how it works in C++ — high level behavior with ability to control low level details.