Effective C++ 学习日记
Effective C++ 学习日记&&1
听说Effective C++这本书很不错,来学习一下,并做个记录。
C++ 多重泛型编程
1.过程
2.面向对象
3.函数
4.泛型
5.元编程
C++可看为由四个次语言组成的集合:C,OO,Template, STL.
Prefer consts,enums and inlines to #define
宁可以编译器替换预处理器
#define ASPECT_RATIO 1.635
ASPECT_RATIO 记号名称可能从未被编译器看见,或在编译器处理源码之前被预处理器移走了,可能并未进入记号表。
解决方法:
const double aspectRatio = 1.635;
常量
常量指针
常量定义通常置于头文件便于被不同源码包含,有必要将指针声明为const.
例如定义常量字符串:
const char* const authorName = "Zac Lipschiyz";
使用string更好:
const std::string authorName = "Zac Lipschiyz";
class 专属常量
为了将常量作用于限制于class内,使用成员变量;
为了只有一份实体,使用static;
class GamePalyers
{
private:
static const int NumTurns = 5;
int scores[NumTurns];
};
上述为声明式而非定义式,如果实现文件中需定义式:
const int GamePalyers::NumTurns;
赋初值可在声明时,也可在定义时,但不可重复赋值。
成员变量是可以被封装的,而#define不行。
注意如果编译器不允许“static 整数型 class 常量”完成“int class 初值设定”,可用enum来替代,一个枚举类型的数值可权充ints被使用。
class GamePalyers
{
private:
enum { NumTurns = 5 };
int scores[NumTurns];
};
the enum hack值得了解
一、不想让别人获取整数常量的指针或引用,可用enum;
二、模板元编程的基础技术。
预处理器
#define误用宏,宏看起来像函数,但不会招致函数调用带来的额外开销:
#define CALL_WIHT_MAX(a, b) f((a) > (b) ? (a) : (b))
定义时所有的实参要加上小括号,单尽可能不用
int a = 5, b = 0;
CALL_WIHT_MAX( ++a, b );
CALL_WIHT_MAX( ++a, b + 10 );
这种调用不堪入目,还好可用template inline函数。
template inline函数
可获得宏带来的效率及一般函数的所有可预料行为和类型安全性。
template<typename T>
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a : b);
}
callWithMax是个真正的函数,遵守作用域和访问规则,可用于类中。
请记住
对于单纯常量,最好用const对象或enums替换#defines;
对于形似函数的宏,最好改用inline函数来替换#defines.
尽可能使用const
const指定一个语义约束,不该被改动的对象。
char greeting[] = "Hello";
char* p = greeting; // non-const pointer, non-const data
const char* p = greeting; // non-const pointer, const data
char* const p = greeting; // const pointer, non-const data
const char* const p = greeting; // const pointer, const data
const data两种写法
void f1(const Widget* pw);
vodi f2(Widget const * pw);
STL迭代器指针
T* const // const pointer, non-const data
const T* // non-const pointer, const data
iterator与const_iterator区别
const + iterator:
std::vector<int> vec = { 1, 2, 3 };
const std::vector<int>::iterator iter = vec.begin(); //T* const
*iter = 10; //const pointer, non-const data
++iter; //error
const_iterator:
std::vector<int> vec = { 1, 2, 3 };
std::vector<int>::cosnt_iterator iter = vec.begin(); //const T*
*iter = 10; //error
++iter; //non-const pointer, const data
const于函数声明的应用
class Rational { ... };隐式转换为
const Rational operator* (const Rational& lhs, const Rational& rhs);
const避免像两个数值乘积后再赋值,有可能隐式转换为bool类型,造成与内置类型不兼容的情况,故将回传值声明为const,避免赋值修改情况。
const成员函数
将const实施于成员函数,是为了确认该成员函数可作用于const对象身上。
class TextBlock
{
public:
TextBlock(const std::string text)
:text_(text)
{}
virtual ~TextBlock() = default;
const char& operator[](std::size_t position) const { return text_[position]; }
char& operator[](std::size_t position) { return text_[position]; }
private:
std::string text_;
};
对比输出:
TextBlock tb("hello");
std::cout << tb[0] << std::endl; //h
const TextBlock tb1("world");
std::cout << tb1[0] << std::endl; //w
这不足以体现区别,不妨添加print函数:
void print(const TextBlock& ctb)
{ std::cout << ctb[0] << std::endl; }
此时print函数只会调用,因为入参由const限定:
const char& operator[](std::size_t position) const { return text_[position]; }
而如果进行修改:
TextBlock tb("hello");
std::cout << tb[0] << std::endl;
print(tb);
tb[0] = 'x';
const TextBlock tb1("world");
std::cout << tb1[0] << std::endl;
print(tb1);
tb1[0] = 'y'; //ERROR
错误原因是试图对const返回值进行赋值操作。
bitwise constness
const成员函数不可以更改对象内任何non-static成员变量。
如果这样的成员函数:
char& operator[](std::size_t position) const { return pText_[position]; }
private:
char* pText_;
那么如下调用会发生:
char test[] = "world";
const TextBlock tb2(test);
std::cout << tb2[0] << std::endl; //w
char* pc = &tb2[0];
pc[0] = 'x';
std::cout << tb2[0] << std::endl; //x
logical constness
一个const成员可以修改它所处理的对象内的某些bits.
private:
char* pText_;
std::size_t text_length_;
bool length_is_valid_;
std::size_t TextBlock::length() const
{
if (!length_is_valid_)
{
text_length_ = std::strlen(pText_); //ERROR
length_is_valid_ = true; //ERROR
}
return text_length_;
}
text_length_和length_is_valid_都可能被修改的,但是编译器会报错,因为编译器都认定bitwise constness.
解决办法:
利用C++的一个与const相关的摆动场:mutable(可变的)。
mutable释放掉non-static成员变量的bitwise constness约束。
private:
char* pText_;
mutable std::size_t text_length_;
mutable bool length_is_valid_;