条款02 03
- 常量,const 或者enum替代#define
- 函数宏 inline 替代 #define
条款04 尽可能使用 const
- 对于 const 成员函数,编译器强制实施的是bitwise constness,不希望成员变量有改变。为了实现conceptual constness,,考虑mutable关键字
- const 声明,可以帮助在编译期发现问题。
- const 版本与 non-const 版本函数实质等价时,non-const版本调用const版本
class textBook
{
public:
const char& operator[](sdt::size_t pos) const
{
...
}
char& operator[](sdt::size_t pos)
{
return const_cast<char&>(
static_cast<const TextBook&>(*this)[pos]
);
// static_cast 避免重复调用
}
};
条款03 使用前初始化
-
内置类型初始化是未定义行为
栈上变量:值不确定
全局变量或者静态变量:默认空初始化 -
非内置类型初始化与赋值的区别
对于类类型来说,最好使用初始化列表。使用初始化列表少了一次调用默认构造函数的过程
-
初始化列表
初始化列表执行在构造函数体之前。比构造函数中初始化效率更高。- 顺序
- 初始化列表中与声明顺序有关,与初始化列表顺序无关。(注意基本类型全局变量初始化)
- 继承 初始化顺序
- 必须使用初始化列表
- const 或者 reference 类型 成员变量
- 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化
-
不同编译单元内 nonlocal static 对象 为保证初始化顺序,考虑使用单例模式(local static 替代 non-local static)
-
默认初始化
条款05
C++,默认添加的函数
- 默认构造函数(无参)
- 拷贝构造(浅复制)
- 析构 (non-virtual 非虚函数)
- 拷贝赋值
- 移动构造 C++11
- 移动赋值 C++11
拒绝生成默认函数情况
所有编译器产出的函数都是 public
template<class T>
class NamedObject {
public:
NamedObject(std::string& name , const T& value);
//假设并未声明 operator =
private:
std::string& nameValue; //这如今是个reference
const T objectValue; //这如今是个const
};
当执行以下代码时
std::string newDog("Persephone");
std::string oldDog("Satch");
NamedObject<int> p(newDog, 2);
NamedObject<int> s(oldDog, 36);
p = s; //现在 的成员变量该发生什么事?
假设此时可以生成默认复制构造函数:
赋值前 p.nameValue 与 s.nameValue 指向各自的string 对象。
赋值后 p.nameValue 指向 s.nameValue对应的string对象。
这显然与 引用 & 的语义不符合。 因此 编译器 会拒绝赋值动作,编译报错。
面对"内含 const 成员" (如本例之 objectValue) classes 编译器的反应也一样。更改 const 成员是不合法的,所以编译器不知道如何在它自己生成的赋值函数内面对它们。
如果某个 base classes copy ass nment 操作符声明为 private ,编译器将拒绝为其 derived classes 生成一个 copy assignment 操作符。毕竟编译器为 derived classes 所生的 copy assignment 操作符想 象中可以处理 base class 成分(见条款 12) ,但它们当然无法调用 derived class 无权调用的成员函数。编译器两手一摊,无能为力。
- 指针常量&&常量指针
const在星号左边,被指向的目标不可变;const在星号右边,指向的位置不可变;
char greeting[] = "hello";
char * p = greeting; // 普通指针
const char * p = greeting; // 指针指向位置可变,内容不可变
char const * p = greeting; // 指针指向位置可变,内容不可变
char * const p = greeting; // 指针指向位置不可变,内容可变
const char * const p = greeting; // 指针指向位置不可变,内容不可变
const char const * p = greeting; // 指针指向位置不可变,内容不可变
- const 重载
普通对象,优先访问普通方法; const 对象只调用const方法
const对象默认调用const成员函数,非const对象默认调用非const成员函数;在同时存在const函数和非const重载函数的前提下,若非const对象想调用const成员函数,则需要显示的转化,例如(const Student&)obj.getAge();
若const对象想调用非const成员函数,同理进行强制类型转换 const_cast <Student&>(constObj).getAge();(注意constObj一定要加括号)
当类中只有一种函数存在的情况:
非const对象可以调用const成员函数或者非const成员函数。const对象只能调用const成员函数,若直接调用非const成员函数编译器会报错。
- mutable
const 成员函数,要求函数内部不能对成员变量进行修改。为了规避这个要求带来的影响,C++引入了mutable 关键字。允许被
mutable修饰的成员,在const函数中被修改。 在多线程操作中使用
class
对于C++类的const成员函数,logical constness的观点允许修改它所处理的对象内的某些bits,但是bitwise const的观点是不能改变对象内的任何一个bit。写一个const成员函数,你想在函数内部给对象成员重新赋值,但是编译器坚持一个bit都不让改动,这个时候就加mutable解除限制。
- static 对象与 static 函数
静态成员函数
静态成员函数无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。
1. 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
2. 非静态成员函数可以任意地访问静态成员函数和静态数据成员;
3. 静态成员函数不能访问非静态成员函数和非静态数据成员;
5. inline关键字 zhuanlan.zhihu.com/p/50812510