Effective C++学习
第0章导读
术语(terminology)
声明式(Declaration):告诉编译器某个东西的名称和类型,但略去细节
extern int x;
std::size_t numDigits(int number);
class Widget;
template<typename T>
class GraphNode;
签名式(Signature):揭示函数的参数和返回类型,std::size_t(int)说明函数numDigit
的参数是Int型,返回类型是std::size_t
定义式(Definition):提供编译器一些声明式所漏的细节。被声明为explicit的构造函数比non-explicit兄弟更受欢迎,作者建议除非有特别好的理由允许构造函数被用于隐式转换,建议都加上explicit声明.以组织隐式转换。
初始化(Initialization):给予对象初值
类作为参数传递,最好采用引用类型,而不是pass-by-value
STL是所谓的标准模板库(Standard Template Library),是C++标准程序库的一部分,致力于容器(vector, list, set, map)、迭代器(vector::iterator, set::iterator等等)、算法(for_each, fidn, sort)。建议读者熟悉STL
不明确定义(undefined behavior):野指针、数组索引越界(竭力避免)
int* p = 0;
std::cout << *p;
char name[] = “hello”
char c = name[10]
TR1和BOOST
TR1(Technical Report1):是一份规范,描述加入C++标准程序库的诸多新机能。这些机能以新的class template 和 function template形式体现, 针对的题目有hash table, referencing-consuming,regular expression,所有的TR1组件在命名空间tr1内,后者嵌套与命名空间std内。
boost:是一个组织,同样是一个网站(boost), 提高可移植的、同行评审源码开放的C++程序库。
第1章 让自己习惯C++
条款01 视C++为一个语言联邦(fedreation)
为了了解C++,你必须认识其主要的次语言(sublanguage)。
- C 说到底,C++仍是以C为基础(blocks, statement, preprocessor, built-in data types, array, pointers)。但是没有templates, exception, overloading
- objected-oriented C++.包括构造函数,析构函数, 封装(encapsulation), 继承(inheritance)、多态(polymorphism)、virtual函数(动态绑定)
- templateC++
- STL
条款02 尽量以const, enum, inline替换#define(宁可以编译器替换预处理器)
#define PI 3.14
编译过程如图:
#define在预处理阶段被预处理器移走, 可能会带来编译错误。
解决办法:
const double PI = 3.14
特殊情况:
如果是字符串常量,则需要两个const,限制指针以及其指向的内容均不可变
const char* const a = "nihao"//第一个const被指物不可变(*左侧),第二个限制指针本身不可变(*右侧)
//上一行代码等同于 char const * const a = "你好"(关键看const的位置和*的位置关系)
//第二种写法(建议)
const std::string autorname("Scott")
如果是class专属常量,按下声明
class GamePlayer
{
private:
static const int NumTurns = 5;//声明常量式
int score[numTurns];//使用常量式
}
class专属常量不同于一般常量,一般常量需要给出定义式,专属常量给出声明式就可以使用, 如果必须提供专属常量定义式,按如下定义:
const int GamePlayer::NumTurns;//定义式应该放在实现文件(.cpp),并且不需要再次赋值
enum最大的好处是无法取址以及无法引用,适当的情况下采用enum也可。
class GamePlayer
{
private:
enumerate{ NumTurns = 5};//声明常量式
int score[numTurns];//使用常量式
}
函数模板替代宏
参考代码:
typename<typename T>
inline void CallWithMax(const T&a, const T&b)
{
f(a > b ? a : b);//a和b中的较大值作为参数
}
总结
- 对于单纯常量,采用const和enum替代#define
- 对于形似函数的宏,采用inline函数替换#define
条款03 尽可能的用const
char greeting[] = "Hello";
char* p = greeting; //p和(*p)都不是常量
const char* p = greeting //(*p)是常量(被指物)
char* const p = greeting //p是常量(指针本身)
const char* const p = greeting //p和(*p)都是常量
const在STL中的应用
STL迭代器中的T指针是一个T const指针,也即可以改变*iter的值,但是不能改变iter的值。
如果想要与上述情况相反,则采用const_iterator
std::vector<int> vec;
const std::vector<int>::iternator iter = vec.begin(); //相当于T* const
*iter = 10;
++iter; //不可
std::vector<int>::const_iternator cIter = vec.begin(); //相当于const T*
*iter = 10 //不可
++iter;
cosnt在函数声明式的应用
-
返回一个const对象(一般是指针类型或者引用类型)
-
const用于成员函数
成员函数参数采用引用传递或者指针,采用const修饰
限定不能修改成员变量(除了static类型的)如何修改const变量的值?
const MyString hello("hello"); //MyString是自己定义的一个类
cout << hello << endl; //hello
char* a = &hello[1]; // char& operator[](int n) const;
cout << "a: " << a << " " << endl; //a:e
*a = 'l';
cout << hello << endl; //hlllo
这就是所谓的logical constness,一个const成员函数可以修改成员变量的某些bits。
使用mutable关键字仍然可以达到上述目的,const成员函数可以在函数实现中更改mutable成员变量。
总结
- const可用于对象,函数参数,函数返回类型,成员函数本体
- const成员函数和non-const成员函数有着实质等价的实现时, 让non-const版本调用const版本可避免代码重复。