Effective C++阅读笔记 一

1,尽量用const或者enum代替#define。

        #define,在预编译的时候,系统只是进行单纯的文本替换,而不存在类型检查,所以可能存在风险。

2,对于形似函数的宏定义,最好用inline模板进行替换。

        #define只是进行文本替换,虽然不会带来函数的额外开销,但有时候很出错,尽管给宏的“实参”加上括号,也不能彻底避免,例如:

#define CALL_WITH_MAX(a,b) func((a)>(b)?(a):(b))

int a = 10, b = 5;
CALL_WITH_MAX(++a, b);        //此处a累加了两次
CALL_WITH_MAX(++a, b+10);    //此处a累加了一次

        这里依旧会导致导致奇怪的bug。

3,尽量多使用const。

        当const修饰指针的时候,如果const在*左边,表示指针指向的变量是常量,如果const在右边,表示这个指针是常量;如果都存在,则表示都是常量。所以我们在定义不可改变的字符串的时候,最好像这样:

const char* const name1 = "beijing";
const std::string name2 = "beijing";

        对于stl中的迭代器,也可以用const修饰,而且也存在const_iterator。

    std::vector<int> intVector{1,3,5,7};
	const std::vector<int>::iterator iter = intVector.begin();
	*iter = 10;
	iter++;			//错误,因为iter为const;

	std::vector<int>::const_iterator citer = intVector.begin();
	*citer = 5;     //错误,因为*citer为const
	citer++;

        用const修饰函数的返回值,可以在保持安全性和高效性的基础上减少程序员失误造成的意外。而对于函数的参数,如果我们没有修改参数的必要时,也可以修饰为const,预防一些错误,如不小心把"=="写成了"="而引发的未知错误。

        此外,也可以把const当作函数重载的标准。

        https://mp.csdn.net/mp_blog/creation/editor

public:
	void func()const
	{
		std::cout << "const" << std::endl;
	}

	void func()
	{
		std::cout << "non-const" << std::endl;
	}

或者:

void func(int const*b)
{
	std::cout << "const" << std::endl;
}

void func(int *b)
{
	std::cout << "non-const" << std::endl;
}

        此外,我们可以用mutable来解除const的限制。

public:
	void func()const
	{
		c = 10;
		std::cout << "const" << std::endl;
	}

private:
	mutable int c = 0;

        但是,当const和non-const成员函数内容相同的时候,我们应该只保存non-const版本避免代码重复。

4,在变量使用前将其初始化。

        不要混淆了变量的初始化与赋值。

        成员变量的初始化发生在构造函数之前,也就是说在构造函数中是对成员变量的赋值,而非初始化。

        成员变量的初始化有两种,一种是声明的时候进行定义,另一种是成员列表初始化,两种都可以进行初始化。但是如果两种都使用了,编译器只会默认调用列表初始化。

class B {
public:
	B() :a(A(5))
	{
		a = A(3); //此处为赋值
	}

public:
	A a = A(8);
};

         这种情况下,只会调用A(5)和A(3)。使用列表初始化的效率比较高。如果我们只在构造函数里进行赋值的方式“初始化”,那么编译器会调用成员变量的默认构造函数,然后在再构造函数中对成员变量进行赋值,这样就带来了不必要的开销。甚至如果没有合适的构造函数,会报错。

        此外,对于const成员变量,无法进行赋值,所以只能在声明的时候初始化,或者用成员列表初始化的方式初始化。

        此外,基类的初始化早于派生类,而且非成员变量是按照声明的顺序进行初始化。静态成员变量的初始化是最先完成的。

        对于每一个编译文件(cpp)和他们包含的头文件组成一个编译单元,对于不同单元的non_local static(函数内声明的static对象为local static,其他的被称为non-local static)对象的初始化没有固定的顺序。(不是很理解)。

        为了避免不同编译单元的初始化次序问题,最好用local static代替non-local static,可以考虑用单例的方式来实现这个需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值