1 让自己习惯C++
来源:互联网 发布:孩子网络借贷怎么办 编辑:程序博客网 时间:2024/06/05 04:25
2017年8月10日 15:05:39
1. 视C++为一个语言联邦
C++已经是个多重范型编程语言,一个同时支持过程形式、面向对象形式、
泛型形式、元编程形式的语言。
C++主要的次语言:
C : C++的基础,但C有局限:没有模版、没有异常、没有重载……
Object-Oriented C++: class、封装、继承、多态、virtual函数(动态绑定)……
Template C++: C++的泛型编程部分
STL : STL是一个template程序库。它读容器,迭代器,算法以及函数对象的规约有极佳的紧密配合与协调。
对于内置类型来说:pass-by-value 比 pass-by-reference高效
对于用户自定义类型class来说,pass-by-reference-to-const 往往更好
C++高效编程守则视情况而变化,取决于使用C++的哪一部分。
2. 尽量以 const, enum, inline 替代 #define
#define 的内容 可能没有被编译器看到,就被预处理器拿走,可能并没有进入记号表
当以常量替换 #define 时,有两种特殊情况:
(1)定义常量指针:
const char * const authorNmae = "Zhangyan";
或者 const std::string authorNmae = "Zhangyan";
(2)class 专属常量
类中的常量,为了保证作用域限制于class内部,必须加const
为了保证此常量最多只有一份实体,必须成为static成员
即:static const int Num = 6;
注意:该式子只是声明。但 static const 变量不需要实例,就可以使用(其他变量都要实例,才能使用,
且在声明时,不能赋初值)。
如果编译器错误处理,一定要实例,那么只需要: const int A::Num;
把这个式子放在实现文件(.c文件)。因为class内部已经声明时,获得初值,所以定义时不可以再赋值。
#define 并不重视作用域,不提供任何封装性,所以不能将class专属常量定义为宏。而const提供封装性。
如果编译器不允许 static const 在类内赋初值,而又要用该常量,来作为数组大小,此时可以用enum
对enum和define取地址是不合法的,而对const取地址合法
enum和define一样,不会导致非必要的内存分配。而优秀的编译器,同样不会为“整型const对象”设定另外的存储空间
对于宏函数来说,可以用inline函数代替。
3. 尽可能使用const
某些东西声明为 const 可以帮助编译器侦测出错误用法。
对于迭代器来说:
const std::vector<int>::iterator iter = vec.begin();
此时,相当于 char * const,即,iter的指向不能发生改变。
std::vector<int>:: const_iterator citer = vec.begin();
此时,相当于 char const *,即:citer指向的对象的值,不能发生改变
对于函数返回值来说:
const 往往可以降低因客户错误而造成的意外,而不至于放弃安全性和高效性
例如: class A
{
const A operator = (A &a, A &B);
};
如果不加 const,那么 A a,b,c; (a * b) = c; 将调用成功
const 成员函数:
目的:让该 const 成员函数可作用于 const对象身上。
意义:(1) 使得 class 接口变得容易理解
(2) 只能操作 const 成员函数。(因为,操作非const成员函数,可能会改变成员变量,
为了避免出现在这种情况,直接操作非const成员函数禁止)。
const 可以作为重载条件
const 成员函数不可以更改对象内任何 non-static 成员变量,如果需要改变,可以在该变量定义前,加 mutable
在const 和 non-const 成员函数中避免重复
因为这两者的内容,往往一致,为了避免代码重复,就是用 non-const 来调用 const 成员函数。
char &opeartor[] (std::size_t position)
{
return
const_cast<char &>(static_cast<const TextBlock&>(*this)[position]);
}
如果只是调用operator[],那么会递归,栈溢出,因此需要指明调用 const opeartor[]
如果想用 const 成员函数 调用 non-const 成员函数,是错误的,因为对象可能因此改动。
4. 确定对象被使用前已经被初始化
永远在使用对象之前先将它初始化。对于无任何成员的内置类型,必须手工完成此事。
初始化的责任在构造函数身上,因此:确保每一个构造函数都将对象的每一个成员初始化。
C++规定,对象的成员变量的初始化发生在进入构造函数本体之前。
因此,成员变量的初始化,应该在初始化列表完成,而不是在构造函数内,用 ‘=’来赋值。
(对于赋值操作来说,大多数类型会先调用构造函数,发现在初始化列表没有,然后再调用赋值运算符)
即使是一个无参的构造函数,也应该调用初始化列表,来初始化成员变量:
A::A() : index()
{ }
编译器会为用户自定义类型之成员变量自动调用默认构造函数。
const 和 reference 成员变量,一定要使用初始化成员列表。
简单的方法是:都使用成员列表初始化。
但是大量在初始化列表,会导致重复。此时可以选择“赋值表现和初始化一样好”的成员变量,将其初始化移到,
一个private成员函数,然后所有的构造函数,再调用这个函数。
C++的初始化顺序:
(1)基类早于派生类初始化
(2)class 的成员变量总是以其声明次序被初始化,而不是初始化成员列表中的顺序。
对于:跨编译单元之间初始化次序的问题
C++对于“定义于不同编译单元内的non-local static 对象”的初始化次序并没有明确的定义。
所以当不同的编译单元,相互依赖,又要确保构造顺序时,最好的方法是加强程序设计。
比如:使用类似单例模式的行为,可以创造一个 static 成员函数,返回一个已经初始化好的对象,
其他类需要使用时,直接调用这个函数即可。
但是 内涵static对象 可能造成多线程系统中带有不确定性。 解决的方法是:在单线程启动时,
就手工调用所有static函数,进行初始化。
(编译单元:多个.c文件)
阅读全文
0 0
- 《Effective C++》1-让自己习惯C++
- 【读书笔记】Effective C++-1 让自己习惯C++(之一)
- 【读书笔记】Effective C++-1 让自己习惯C++(之二)
- 【读书笔记】Effective C++-1 让自己习惯C++(之三)
- 《Effective C++》让自己习惯C++:条款1-条款4
- Effective C++读书笔记1(让自己习惯C++)
- Effective C++读书笔记1(让自己习惯C++)
- <<Effective C++>>读书笔记1: 让自己习惯C++
- 1,让自己习惯C++
- 1、让自己习惯c++
- 1 让自己习惯C++
- 1 让自己习惯C++
- Effective C++(一)让自己习惯C++
- Effective C++(一)让自己习惯C++
- effective c++-让自己习惯c++
- 《Effective C++》第一章:让自己习惯C++
- 如何写出高效C++(让自己习惯C++)
- Effective C++ --1 让自己习惯C++
- 使用 Gradle 对应用进行个性化定制
- C语言(22)1的个数
- Leetcode刷题Day3 Palindrome Number
- javascrip练习——简单模拟全选功能
- Tempter of the Bone
- 1 让自己习惯C++
- css样式的过渡问题
- 篇MongoDB导出,导入,备份
- html5开发之viewport使用
- 攻击“王者荣耀”的勒索病毒SLocker解读
- 织梦 分页码制作
- jQuery 遍历
- 使用加速度传感器完成摇一摇功能
- 显示润乾报表提示Access denied for user 'root'@'localhost' (using password: YES)问题