masterminds of programming 翻译 (三)

One fundamental difference between C++ and Java is the way pointers are implemented. In some ways, you could say that Java doesn’t have real pointers. What differences are there between the two approaches?

C++Java一个根本区别在于其指针的实现。从某种程度上你可以说Java没有真正的指针。那么这里这两种实现有什么区别呢?

 

Bjarne: Well, of course Java has pointers. In fact, just about everything in Java is implicitly a pointer. They just call them references. There are advantages to having pointers implicit as well as disadvantages. Separately, there are advantages to having true local objects (as in C++) as well as disadvantages.

Bjarne: 恩,Java当然是有指针的。事实上,Java里的任何对象都是一个隐式指针。 他们只是称它们为引用罢了。隐式指针有好处也有坏处。同样,拥有真正的局部对象(就像在C++里那样)也是一把双刃剑。

 

C++’s choice to support stack-allocated local variables and true member variables of every type gives nice uniform semantics, supports the notion of value semantics well, gives compact layout and minimal access costs, and is the basis for C++’s support for general resource management. That’s major, and Java’s pervasive and implicit use of pointers (aka references) closes the door to all that.

C++支持对每种类型的局部变量和真正的成员变量进行栈分配的选择提供了漂亮统一的语义表达,提供对值语义的支持,提供紧凑的数据存储格式和最小成本的访问,这也是C++对一般资源管理支持的基础。这是主要的,Java那种普遍的隐式指针使用(引用)很接近上述一切。

 

Consider the layout tradeoff: in C++ a vector<complex>(10) is represented as a handle to an array of 10 complex numbers on the free store. In all, that’s 25 words: 3 words for the vector, plus 20 words for the complex numbers, plus a 2-word header for the array on the free store (heap). The equivalent in Java (for a user-defined container of objects of userdefined types) would be 56 words: 1 for the reference to the container, plus 3 for the container,  plus 10 for the references to the objects, plus 20 for the objects, plus 24 for the free store headers for the 12 independently allocated objects. Obviously, these numbers are approximate because the free store (heap) overhead is implementation defined in both languages. However, the conclusion is clear: by making references ubiquitous and implicit, Java may have simplified the programming model and the garbage collector implementation, but it has increased the memory overhead dramatically—and increased the memory access cost (requiring more indirect accesses) and allocation overheads proportionally.

考虑数据存储格式的权衡:C++里,一个vector<complex>(10)被表示成在自由空间[1]里控制由10个复数组成的数组的一个句柄。这加起来总共有25字长,向量(vector)占用3个字长,外加复数(complex)部分20各自长,外加在自由空间()2个字长的头部[2]Java里相同的东西(对于一个包含用户自定义类型的用户自定义容器)长达56个字:容器的引用1个字,外加容器本身3个字,容器内部对象引用10个字,容器对象本身20个字,还有在自由空间里24字长的12个独立分配对象的头部。显然,这些数字只是估算,因为自由空间的额外开销在两种语言中都存在。但是,结论是清楚的:通过到处使用隐式引用,Java可能确实简化了编程模型以及垃圾回收实现,但这也大大增加了内存的额外开销、内存访问的额外开销(需要更多的间接访问)以及同比例的分配的额外开销。 

 

What Java doesn’t have—and good for Java for that—is C and C++’s ability to misuse pointers through pointer arithmetic. Well-written C++ doesn’t suffer from that problem either: people use higher-level abstractions, such as iostreams, containers, and algorithms, rather than fiddling with pointers. Essentially all arrays and most pointers belong deep in implementations that most programmers don’t have to see. Unfortunately, there is also lots of poorly written and unnecessarily low-level C++ around.

Java所没有的-Java也是好的-CC++在进行指针算数运算时可能出现的指针错用可能。 一个编写良好的C++代码其实也不会受此困扰:人们使用高级抽象类,像是输入输出流类(iostream),容器类(container),和算法类(algorithms)而不是乱用指针。本质上所有数组和大多数指针都属于底层实现,大多数程序员并不是非去了解不可。不幸的是,在我们身边还存在很多写的不好也不需要的C++底层代码

 

There is, however, an important place where pointers—and pointer manipulation—is a boon: the direct and efficient expression of data structures. Java’s references are lacking here; for example, you can’t express a swap operation in Java. Another example is simply the use of pointers for low-level direct access to (real) memory; for every system, some language has to do that, and often that language is C++.The “dark side” of having pointers (and C-style arrays) is of course the potential for misuse: buffer overruns, pointers into deleted memory, uninitialized pointers, etc. However,  in well-written C++ that is not a major problem. You simply don’t get those problems with pointers and arrays used within abstractions (such as vector, string, map, etc.). Scoped resource management takes care of most needs; smart pointers and specialized handles can be used to deal with most of the rest. People whose experience is primarily C or oldstyle C++ find this hard to believe, but scope-based resource management is an immensely powerful tool and user-defined with suitable operations can address classical problems with less code than the old insecure hacks. For example, this is the simplest form of the classical buffer overrun and security problem:

但是指针以及指针相关的操作还是有它好的一面并使其拥有一席之地:对数据结构直接有效的表达。Java的引用在这方面就显得欠缺;比如,你在Java里不能表达一个swap操作。另一个简单的例子是对于每个操作系统,总得有指针去应对直接的底层的(真正)内存访问,一些语言不得不去做这件事,这经常落在了C++的头上。拥有指针(以及C的数组)的“黑暗面”当然是潜在的错用:缓存溢出、指向已经释放的内存的指针、未初始化的指针等。然而,对于一个编写良好的C++代码这不是主要问题。你只要使用抽象类(如向量类(vector)、字符串类(string)、映射类(map))就不会有指针和数组带来的麻烦。带有作用域的资源管理机制可以很好的处理大部分需求;智能指针和特定句柄可以解决余下那些。那些拥有的经验主要是C和老式C++的程序员觉得这难以置信,但是基于作用域的资源管理系统确实是一个极为强大的工具,配以良好操作的用户自定义类使用比过去那些不安全的“技巧”更少的代码就可以解决经典的问题。例如,这是一个最简单的经典缓存溢出的安全性问题:

 

char buf[MAX_BUF];

gets(buf); // Yuck!

 

Use a standard library string and the problem goes away:

使用标准库里的字符串类(string),这个问题就没了:

string s;

cin >> s; // read whitespace separated characters

 

These are obviously trivial examples, but suitable “strings” and “containers” can be crafted to meet essentially all needs, and the standard library provides a good set to start with.

这些显然是没什么价值的例子,但合适的“字符串类(string)”和“容器类(container)”可以精工细磨出来去满足本质上所有需求,而标注库可以提供一个良好的工具集合去开始这项工作。



[1] 这里所说的自由空间(free store)和平时所说的堆(heap)类似,C++newdelete申请和释放的空间便是在这个自由空间里进行的。这里vector本身的元素还是在栈(stack)里,只是控制它的句柄在自由空间里。    --译者注

[2] 这里头部即句柄译者注

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值