再次学习《Effective C++》01

背景:
C++的难学,不仅在其广博的语法,以及语法背后的语义,以及语义背后的深层思维,以及深层思维背后的对象模型;C++的难学还在于它提供了四种不同而又相辅相成的编程范型 (programming paradigms):procedural-based,object-based,object-oriented,generics(泛型形式)。

用途:
这本书的最佳用途就是彻底了解C++如何行为、为什么那样行为,以及如何运用其行为形成优势。盲目应用书中条款是非常不合适的,但如果没有好理由,你或许也不应该违反任何一个条款。

术语:
声明式(对象声明式、函数声明式,类声明式、模板声明式)。
定义式的任务是提供编译器一些声明式所遗漏的细节,对对象而言,定义式是编译器为此对象拨发内存的地点;对函数或者函数模板而言,定义式提供了代码本体;对类或者类模板而言,定义式列出它们的成员。
初始化是“给予对象初值”的过程。对用户自定义类型的对象而言,初始化由构造函数执行。
STL(Standard Template Library)是C++标准程序库的一部分。包括容器、迭代器和算法。
接口=函数的签名

条款总结分析

1.让自己习惯C++:

条款01:视C++为一个语言联邦

C++高效编程守则视状况而变化,取决于你使用C++的哪一部分。

条款02:尽量以const,enum,inline替换#define

有了const、enum和inline,我们对预处理(特别是#define)的需求降低了,但并非完全消除。#include仍然是必需品,而#ifdef/#ifndef也继续扮演控制编译的重要角色。

1.对于单纯常量,最好以const对象或enums替换#defines.
2.对于形似函数的宏,最好改用inline函数替换#define.

条款03:尽可能使用const

const的一件奇妙事情是,它允许你指定一个语义约束,也就是指定一个“不该被改动”的对象,而编译器会强制实施这项约束。它允许你告诉编译器和其他程序员某值应该保持不变。只要这(某值保持不变)是事实,你就应该确实说出来

1.理解:令函数返回一个常量值,往往可以降低因客户错误而造成的意外,而又不至于放弃安全性和高效性。
2.const成员函数:将const实施于成员函数的目的,是为了确认该成员函数可作用于const对象身上。这一类成员函数之所以重要,基于两个理由:其一,它们使class接口比较容易被理解;其二,它们使“操作const对象”成为可能。这对编写高效代码是个关键,因为改善C++程序效率的一个根本方法是以pass by reference-to-const方式传递对象

/*两个成员函数如果只是常量性不同,可以被重载,以下代码用来说明这一点:*/

/*功能类:用来表现一大块文字*/
class TextBlock{
public:
    ……
    const char& operator[](std::size_t position) const{return text[position];}
    char& operator[](std::size_t position) const{return text[position];}
private:
    std::string text;
}
/*调用*/
TextBlock tb("Hello");
std::cout << tb[0];          //调用non-const TextBlock::operator[]

void print(const TextBlock& ctb)
{
    std::cout << ctb[0];  //调用const TextBlock::operator[]
    ……
}
/*只要重载operator[]并对不同的版本给予不同的返回类型,就可以令const和non-const TextBlock&获得不同的处理:*/
std::cout << tb[0];   //OK,读一个non-const TextBlock
tb[0] = 'x';          //OK,写一个non-const TextBlock,tb的operator[]返回类型是reference to char
std::cout << ctb[0];  //OK,读一个const TextBlock
ctb[0] = 'x;          //error:写一个const TextBlock,错误原因:该赋值企图对一个“由const版之operator[]返回”的const char&施行赋值动作。

3.成员函数如果是const意味着什么?以下两种方式中编译器强制实施bitwise constness,但编写程序时应该使用“概念上的常量性”(conceptual constness)
bitwise constness(physical contness) :成员函数只有在不更改对象之任何成员变量(static除外)时才可以说是const.这正是C++对常量性的定义。不幸的是许多成员函数虽然不十足具备const性质却能通过bitwise测试。
logical constness:上一种方式中不幸通过bitwise测试的情况引出了此种方式,也就是另一种理解。一个const成员函数可以修改它所处理的对象内的某些bits,但只有在客户端侦测不出的情况下才可以如此。

4.const是个奇妙且非比寻常的东西,在指针和迭代器身上;在指针、迭代器及reference指涉的对象身上;在函数参数和返回类型身上;在local变量身上;在成员函数身上。

5.const版本调用non-const版本:错误。曾经承诺不改动的那个对象被改动了。non-const版本调用const:正确。non-const成员函数本来就可以对其对象做任何操作。

条款04:确定对象被使用前已先被初始化

1.区分赋值和初始化;
2.为内置对象进行手工初始化,因为C++不保证初始化它们;
3.构造函数最好使用成员初值列(member initialization list),而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排序次序应该和它们在class中的声明次序相同;
4.为免除“跨编译单元之初始化次序”问题,请以local static对象替换non-local static对象
所谓static对象,其寿命从被构造出来直到程序结束为止,因此stack和head-based对象都被排除。这种对象包括global对象、定义域namespace作用域内的对象、在classes内、在函数内、以及在file作用域内被声明为static的对象。函数内的static对象称为local static对象(因为它们对函数而言是local),其他static对象称为non-local static对象。程序结束时static对象会被自动销毁,也就是他们的析构函数会在main()结束后自动调用。

这块的问题是:如果某编译单元内的某个non-local static对象的初始化动作使用了另一编译单元内的某个non-local static对象,它所用到的这个对象可能尚未被初始化,因为C++对“定义域不同编译单元内的non-local static对象”的初始化次序并无明确定义。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tingzhushaohua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值