C++编程思想 第二卷 勘误

注:这是我本人在看C++编程思想 第二卷:实用编程技术(刁成嘉译)时发现的翻译问题。特此列一表,供各位参考及讨论 。

本人收集的翻译不妥之处大部分为那些狗屁不通之句,影响读者理解之句以及误人子弟之句。关于名词翻译的修改较少,希望能够给各位软件初学者以一定帮助。

若本人勘误有错,欢迎指正。

 

勘误连接
第一章 异常处理 P3 P4 P9 P9 P17 P29
第二章 防御性编程 P32 P36 P48 P50 P52 P52 P52 P53 P53
第三章 深入理解字符串 P63 P65 P67 P75 通篇错误
第四章 输入输出流 P91 P91 P95 P96 P96 P102 P109 P117 P124 P127 P128 P129 P129
第五章 深入理解模板 P138 P154 P156(1) P156(2) P158 P160 P167 P179 P184
   
   
   
   
   
   

 

 

 

 

 

 

 

 

 

第一部分 建立稳定的系统

第一章 异常处理

 P3 函数setjmp( )的行为很特别,因为如果直接调用它,它便会将所有与当前处理器相 关的状态信息(比如指令指针的内容、运行时栈指针等)保存到jmp_buf中去并返回0。在这种情况下,它的 表现和一个普通函数一样。然而,如果使用同一个jmp_buf调用longjmp( ),则函数返回时就像刚从setjmp( )中返回时一样——又回到了刚刚从setjmp( )返回的地方。

原文:The setjmp( ) function is odd because if you call it directly, it stores all the relevant information about the current processor state (such as the contents of the instruction pointer and runtime stack pointer) in the jmp_buf and returns zero. In this case it behaves like an ordinary function. However, if you call longjmp( ) using the same jmp_buf, it’s as if you’re returning from setjmp( ) again—you pop right out the back end of the setjmp( ).

勘误:setjmp( )是一个特殊的函数,因为如果你直接调用,它会保存关于当前处理器状态 的所有相关信息(比如指令指针和运行时栈指针的内容)到jmp_buf中并返回0。假如是这样的话,它与普通函数的表现无异。 然而,如果你调用longjmp( )去使用同一个jmp_buf的话,它(的行为)就会好像你又从setjmp( )回来一样——你 恰好从setjmp( )(函数体)的末端跳出来。

P4 在C++中使用longjmp()的问题是它不能识别对象。

原文:The problem in C++ is that longjmp( ) doesn’t respect objects;

 勘误:在C++中的问题是,longjmp()它不关心对象。

P9 如果try块之后的异常处理器不能匹配所抛出的异常,那么这个异常就会被传递给位于更高 一层语境中的异常处理器,也就是说函数或try块周围的try块不捕获这个异常。

原文: If none of the exception handlers following aparticular try block matches an exception, that exception moves to the next-higher context, that is,the function or try block surrounding the try block that did not catch the exception.

 勘误:如果某一个特定try块后面的catcher没有一个能匹配所抛出的异常,那个异 常就会移动到更高语境中去,更高的语境即:框在那个不能catch异常的try块外面的函数或try块

P9 在下列两种情况下terminate( )函数也会执行:局部对象的析构函数抛出异常时,栈正在进 行清理工作……

原文:The terminate( ) function also executes if a destructor for a local object throws an exception while the stack is unwinding...

勘误:terminate( )函数会在下列两种情况下执行:正在进行stack unwinding时,局部对 象的析构函数抛出了一个异常

P17 length_error 表明程序试图产生一个长度大于等于npos的对象(语境长度的最大可能值 的类型通常为std::size_t)

原文:length_error  Indicates an attempt to produce an object whose length is greater than or equal to npos (the largest representable value of context’s size type, usually std::size_t).

勘误:length_error  表明试图产生一个对象,其长度大于等于npos(npos是环境尺 寸类型所能表示的最大可能值,通常是为std::size_t)

P29 每当函数被调用的时候,有关这个函数的信息被压到运行栈顶部的活动记录实例 (activation record instance, ARI)中,也叫栈结构(stack frame)。典型的栈结构包含调用函数的指令所在的地址(这 样,程序的执行流程可以返回到这个地址),指向这个函数静态父对象的ARI(某个作用域,它在词法上包含被调用函数,这样 这个函数就可以访问全局变量了)的指针,指向调用函数的指针(它的动态父函数)。沿着动态父函数链反复追踪得到的逻辑 结果路径就是动态链,或称其为调用链,读者在这一章的前面见到过它。这就是为什么当异常抛出时执行流程能够回溯,这种 机制使得在彼此缺乏了解的情况下开发出来程序的各个部分,能够在运行时互相传递出错信息。

原文:Whenever a function is called, information about that function is pushed onto the runtime stack in an activation record instance (ARI), also called a stack frame. A typical stack frame contains the address of the calling function (so execution can return to it), a pointer to the ARI of the function’s static parent (the scope that lexically contains the called function, so variables global to the function can be accessed), and a pointer to the function that called it (its dynamic parent). The path that logically results from repetitively following the dynamic parent links is the dynamic chain, or call chain, that we’ve mentioned previously in this chapter. This is how execution can backtrack when an exception is thrown, and it is the mechanism that makes it possible for components developed without knowledge of one another to communicate errors at runtime.

勘误:无论一个函数何时被调用,其信息都会被压入(push)到存在于ARI(activation record instance)中的运行时栈(runtime stack)的顶部,ARI也被称为stack frame。一个典型的stack frame包含正在被调 用的函数的地址(因此执行流程可以返回至那个地址),一个指向函数静态根源的ARI的指针(函数静态根源,function's static parent,是一个在语法上包含被调函数的辖域(scope),因此,被调函数能够访问到对其而言是全局的变量),和一个 调用该函数的函数的指针(被调函数的动态根源)。在逻辑上通过反复跟踪动态根源链而得到路径就是动态链(dynamic chain ),或称为调用链(call chain),这个我们在本章前面提到过它。这就是当一个异常被抛出时一个执行流程怎样回溯的过程 。这个机制也使得,在彼此不了解的情况下开发出来的组件,能够在运行时交换报错信息成为可能。 


第二章 防御性编程

P32 在程序某个特定的地方,应该能够大胆地声明某些条件或其它一些控制方法

原文:At certain points in your program, you should be able to make bold statements that some condition or other holds.

勘误:在程序的某一个地方,你应该能够明确的陈述一些条件或把握。

 P36 由于经营成本方面的考虑,迫使编程人员损害系统的功能性,放弃了代码的可扩展 性,而这正是保持代码持久性所需要的。“如果程序没有坏掉,就不要修改它”,最后的方法是“没法修改它 ——重写算了。”这种情况必须改变。

原文:Management's reluctance to let you tamper with a functioning system robs code of the resilience it needs to endure.“If it’s not broken, don’t fix it” eventually gives way to, “We can’t fix it—rewrite it.” Change is necessary.

勘误:让你玩弄机能系统的而导致的管理上的难度,使你放弃了其(机能系统)持续发展 所需要的有弹性的代码。“如果它没坏,就不要修”最终就导致成了“我们无法修复,重写吧”的情况 。因此,改写代码是必需。

P48 这部分和下面部分内容所包含的代码已经被C++标准正式拒绝了。

原文:DISCLAIMER: This section and the next contain code which is officially unsanctioned by the C++ Standard.

勘误:免责声明:本节及下一节所包含的代码还未被C++标准接受。

P50 它们之间没有什么差别,虽然在编译时没有反对对动态存储区使用输入输出流,但是当尝 试使用输入输出流时,有些编译器会报错。

原文:It shouldn't make a difference, since we're not interfering with iostreams's use of the free store, but when we tried it, some compilers complained.

勘误:这样做应该不会有什么差别,因为iostream使用free storage的时候我们不会受到 妨碍,但是当我们试图这样做的话(iostream使用free storage),有些编译器会报错。

P52 MemCheck工具在Info结构类型的数组中保存全部内存地址、文件名和行号:内存地址是使 用operator new()分配内存时得到的,文件名是new运算符所在的文件的文件名,而行号是new运算符所在行的行号。

原文:The MemCheck facility tracks memory by keeping all addresses allocated by operator new( ) in an array of Info structures, which also holds the file name and line number where the call to new occurred.

勘误:MemChecd组件通过把所有用new()分配的内存地址存放在一个Info结构体数组来跟踪 内存,这个数组也存放了new()被调时所在的文件名和行号。

P52 但是,在这里这样做的目的是发现内存泄漏,而不是调试库。

原文:but our purpose here is to find your leaks; we’re not debugging the library.

勘误:但是我们的目的是找出你自己的内存泄漏。我们不是在对库进行调试。

P52 简单的说,现在做的所有工作就是排列new和delete,将它们进行匹配。

原文:For simplicity, we forward all work for array new and delete to their scalar counterparts.

勘误:为了简单起见,我们将new[],delete[]的工作交给它们的单体版本(就是非数组 new,delete)。

P53 这个例子证实了,可以在如下场合使用MemCheck:代码中使用了流,代码中使用了标准容 器(standard containers),以及代码中某个类的构造函数分配了内存。

原文:This example verifies that you can use MemCheck in the presence of streams, standard containers, and classes that allocate memory in constructors.

勘误:这个例子说明了你可以在有流、标准容器、在构造函数中分配内存的类的情况下使 用MemCheck。

P53 因为调用了MEM_OFF( ),所以后面vector和ostream对operator delete( )的调用过程没 有进行。

原文:Because of the call to MEM_OFF( ), no subsequent calls to operator delete( ) by vector or ostream are processed.

勘误:因为调用了MEM_OFF( ),所以没有对后续vector和ostream对delete( )的调用进行 处理(就是跟踪)。

 


第二部分 标准C++库

 

第三章 深入理解字符串

本章的通篇错误:引用字符串,引用字符数组 全部都改成 引 号内的字符串 引号内的字符数组

P63 如果要生成的新字符串的规模比当前的字符串大或者说是需要截短原字符串,resize( ) 函数就会在字符串的末尾追加空格。

原文:A resize( ) function appends spaces if the new size is greater than the current string size or truncates the string otherwise.

勘误:如果新尺寸比当前尺寸大的话,resize( )函数会在当前字符串后面追加空格,或相 反的,resize( )也可以截断当前字符串。

P65 将变量LookHere表示的位置传送到替换串,这是很重要的,以防字符串from是字符串to的 字串。

原文:It is important to advance the position held in the variable lookHere past the replacement string, in case from is a substring of to.

勘误:将lookHere所表示的位置向前推并超过替换字符串(的长度)是非常重要的,以防 from是to的子串的情况。(举个例子,如果from是"n",to是"nn",如果lookHere的增量是1的话,那么 这个这个字符串就会无限变长)

P67 在语句的右边,程序员几乎可以采用任何一种样式对由单个或多个字符构成的分组进行赋 值。

原文:On the right side of the statement, you can use almost any type that evaluates to a group of one or more characters.

勘误:在语句的右边,你可以使用几乎任何(数据)类型,只要它们可以变成一个由一个 或多个字符构成的组合。

P75 引用文字

原文:quoted literals

勘误:引号内的文字

 


第四章 输入输出流

 

P91 把类型安全检查交给I/O库来完成似乎是欠妥的,尤其是进行大量I/O操作时。

原文:It seems a shame to throw type safety away for an I/O library, especially since I/O is used a lot.

勘误:既然I/O用得很多,那么抛弃对I/O库的类型安全支持显得尤其遗憾。

P91 救助输入输出流

原文:Iostream to the rescue

勘误:来自iostream的帮助 

P95 例如,看看本章前面是如何在头文件中声明Date流操作符的。

原文:Consider, for example, how you would declare the Date stream operators introduced earlier in the chapter in a header file.

勘误:举个例子,设想一下你会如何在头文件里声明本章前面介绍的Date类的流操作符。

P96 可以通过调用流的成员函数来测试错误

原文:You can detect stream errors by either calling certain stream member functions to see if an error state has occurred...

勘误:你可以调用流成员函数来侦测是否有错误状态发生

P96 ...或者如果不关心到底发生了什么错误,而仅仅用来评估流中这个布尔变量的来龙去脉 。

原文:...or if you don’t care what the particular error was, you can just evaluate the stream in a Boolean context.

勘误:或者如果你并不关心到底发生了什么错误,你可以直接把流放入一个逻辑判断语境 中进行评估。(注:诸如if(cin)这样的逻辑判断语句)

P102 重置失败位

原文:不需要原文,这种翻译太恶心

勘误:重置fail bit

P109 ios::showpoint 显示浮点值的小数点并截断字末尾的0

原文:Show decimal point and trailing zeros for floating-point values.

勘误:为浮点值显示小数点及其后面的0

P109 ios::skipws 跳过空格(输入流的默认情况)

原文:ios::skipws Skip white space. (For input; this is the default.)

勘误:ios::skipws跳过空白格(输入流的默认情况)。注:空白格white space指的是空 格,tab,换行符

P117 在这里,不需要知道应用算子是如何创建操纵算子的;仅需知道操纵算子的存在。

原文:You don’t need to know how applicators work to create your own manipulator; you only need to know that they exist.

勘误:你若想创建你自己的操纵符,你没有必要知道应用操作符是如何工作。你只需知道 应用操纵符的存在即可。

P124 当所有的文件处理结束后,关闭文件(到达文件范围末尾)

原文:When the whole file is processed, it is closed (by reaching the end of a scope)

勘误:整个文件处理完毕后,文件关闭(到达作用域末端时)

P127 注意必须将参数设置为char*类型,因为write( )使用专用流(narrow stream)

原文:—notice it must be cast to a char* because that’s what write( ) expects for narrow streams.

勘误:注意将其转换成char*,因为write( )要求窄流(narrow stream)。 PS.后面我们的 刁成嘉副教授又将narrow stream 翻译成了窄字符流

P128 总而言之,读者用这些方法可以创建不同字符类型的流。

原文:In a perfect world, this is all you’d need to create streams of different character types.

勘误:理想状态下,你只需这样就可以创建不同字符类型的流。

P129 例如,对表达式widen('-')来说就是将其参数转变成L'-'(文字语法相当于wchar_t ('-')转变),如果为宽字符流则不进行转换。

原文:The expression widen('-'), for example, converts its argument to L'-' (the literal syntax equivalent to the conversion wchar_t('-')) if the stream is a wide stream and leaves it alone otherwise.

勘误:例如,如果流为宽流,则widen('-')表达式将其参数转换成L'-'(语法上等价于 wchar_t('-')转换),如果不是,就不转换。

P129 如果需要,函数narrow( )将字符转换成char类型

原文:There is also a narrow( ) function that converts to a char if needed.

勘误:如果需要,也有一个转换为char型的narrow( )函数

 


 

第五章 深入理解模板

P138 如果还没有声明Seq是一个模板类型的模板参数,编译器就不会在这里将Seq解释为一 个模板,尽管已经如此使用了它。

原文:If we hadn’t declared Seq to be a template template parameter, the compiler would complain here that Seq is not a template, since we're using it as such.

勘误:(刁成嘉你难道看不出来if hadn't..., would是虚拟语气么?)如果我们没有将 Seq声明为模板的模板型参数,编译器会报错说Seq不是一个模板,因为我们正将它当作一个模板来使用。

P154 一个函数模板要考虑多种特化,在这些特化的模板中对于某个特定的函数模板来说, 如果每一种可能的参数列表的选择都能够匹配该模板的参数列表,那么,这些可能的参数列表选择也都能够匹配另一个函数模 板的参数列表,但反过来却不成立。(我们的刁成嘉教授在寂静了16页之后,终于忍不住又开始即兴发挥了)

原文:A function template is considered more specialized than another if every possible list of arguments that matches it also matches the other, but not the other way around.

勘误:如果每一个能匹配这个函数模板的参数列表,也能够匹配另外一个函数模板的参数 列表,但反过来却不成立,那么这个函数模板被认为比另一个函数板更为特化(more specialized)

P156 ……还因为所有基本的模板参数都由令人感到满意的一个参数列表附加到类名中。

原文:...and because all the primary template's parameters are satisfied by the argument list appended to the class name.

勘误:……还因为跟在类名后面的参数列表符合主模板的所有参数的要求。

P156 这意味着在模板特化的某些方法中至少还有一个方法,其模板参数是“开放的”。

原文:meaning that at least one of the template parameters is left “open” in some way in the specialization.

勘误:意思是在特化时,至少有个一个模板参数可以以某种方式保留“开放”状态。

 P158 ——在这两个模板中无法进行进一步取舍。同样的逻辑错误存在于 第9行到第12行。 (到底是什么逻辑错误,上下文根本没有讲清,请问刁副教授,到底是什么逻辑错误?)

原文:—one is not more specialized than the other. Similar logic applies to lines 9 through 12.

勘误:——没有一个比另外一个更为特化。同样的逻辑也适用于第9~12行。( 我来告诉你吧刁副教授,所谓的逻辑错误就是“没有一个比另外一个更为特化”)

P160 无论何时,一旦对某个类模板进行了实例化,伴随着所有在程序中调用的该模板的成 员函数,类定义中用于对其进行详尽描述的特化代码也就会生成。

原文:Whenever a class template is instantiated, the code from the class definition for the particular specialization is generated, along with all the member functions that are called in the program.

勘误:无论一个类模板何时被实例化,因特定的特化而产生的类定义的代码就会被生成, 该代码同时包含所有在程序中被调用的成员函数。

P167 ("::"左边的限定词必须为关联的限定名称提及一个模板参数)

原文:(The qualifier on the left of the "::" must mention a template parameter for a qualified name to be considered dependent.)

勘误:(要让一个限定名被认为是依赖性的(关联性),"::"左边的限定符必须 提及一个模板参数。)

P179 程序输出了由参数12!实例化后的正确值!并没有警告发出。那么警告是什么呢?警告就是:在程序开始运行前就已经完成了计算! (点评:这翻译很脑残)

原文:That this program prints the correct value of 12! is not alarming. What is alarming is that the computation is complete before the program even runs!

勘误:这段程序输出了12!的正确值并不是一件令人惊奇的事情。令人惊奇的是在程序运行前计算就已经完成了!

P184 (在STATIC_CHECK()中的sizeof调用里面的特殊圆括号,是为了防止编译器认为程序正在试图将sizeof作为函数调用,这是不合法的)

原文:(The extra parentheses inside the sizeof invocation in STATIC_CHECK( ) are to prevent the compiler from thinking that we're trying to invoke sizeof on a function, which is illegal.)

勘误:(在STATIC_CHECK()中,调用sizeof时内部额外的括号是为了防止编译器认为我们正在试图为一个函数调用sizeof,而这样做是非法的)

你可能感兴趣的:(THINKING,IN,C++,编程,c++,function,iostream,exception,stream)