MoreEffectiveC++笔记 3基础议题

1指针和引用的区别

  • 指针可以指向空值,引用必须绑定到另一个变量。
int main(){
	int *p = NULL;
	int &ref = *p;//尝试设置一个绑定到空的引用
	cout<<ref;//g++下编译通过 运行时提示段错误
	return 0;
}
  • 引用必须被初始化,但是指针未初始化是合法的。
int main(){
	int &a;//error: ‘a’ declared as reference but not initialized
	int b = 1;
	int &c = b;
	int *p;
	return 0;
}
  • 引用永远绑定在一个变量上,指针可以重新指向新的对象。
int main(){
	int a = 1,b = 2,c = 3;
	int &ra = a;
	int *pb = &b;
	ra = c;//更改绑定的数值
	pb = &c;//指向新的位置 不更改原先的值
	cout<<a;//3
	cout<<b;//2
	return 0;
}

总结:当指向可能为空或者需要更改指向的对象的时候适合使用指针,此外当我们需要重载一些运算符比如 [ ] 的时候应当返回引用。

2尽量使用C++风格转换

C++ cast功能包括const_cast、static_cast、dynamic_cast、reinterpret_cast。
C传统转换风格写法为 (type)expression。

  • C转换风格不对去除const以及基类转换为子类的转换进行语法区分;C类型转换难以在程序语句中进行识别。
  • static_cast在功能上与C风格是一样的含义,但包含限制(不能把结构体转化为int或者把double转化为指针,也不能去除const属性)
  • const_cast用于去除表达式的const或者volatileness属性,此外的转换都会被拒绝。
  • dynamic_cast用于安全的从父类指针引用转换为子类指针引用,当指针转换失败返回空指针,当引用转换失败抛出异常。除了继承关系外的转换会被拒绝。
  • reintrepret_cast最普通的用处是对函数指针类型进行转换。

3不用对数组使用多态

当我们定义一个子类数组传入到父类形参的函数体中进行遍历时,使用下标读取数组对象时,编译器会根据size决定指针跳跃多少字节来访问下个对象。

class Parent{
	public:
	int i = 1;
};
class Child:public Parent{ //子类多一个整形
	public:
	int j = 2;
};
void foo(Parent pars[],int num){//使用父类形参以求多态
	for(int i = 0;i<num;i++){
		cout<<pars[i].i<<" ";//输出结果1 2 1 2 1 2 1 2 1 2
	}
}
int main(){
	Child childs[10];
	foo(childs,10);
	return 0;
}

例子中的父类包含一个整形,子类除了继承的i之外自身额外定义了j,这样导致子类大小恰好时父类的两倍,编译器在函数中进行遍历时会按父类的size进行下标遍历,导致无法预期的错误。

  • 经过在g++测试,假如父类中定义了虚函数,上文的例子将会正常输出10个1

4避免无用的缺省构造函数

如果定义了带有参数的构造函数,缺省的无参数构造函数就变为无法调用。首先这会带来一些限制,此时我们只能定义栈上的数组。

class A{
public:
	int i;
	A(int i){
		this->i = i;
	}
};
int main(){
	A arr[] = {
		A(1),A(2),A(3)
	};//如果不用vector 唯一定义数组的方法。
	return 0;
}

如果非要建在堆上,那必须定义一个指针的数组,逐个new新的对象。这样我们必须逐个释放堆上空间,而且指针也带来了内存的浪费。或者考虑用placement new技术在一个先分配好的空间里,但是大家都不熟悉。
缺少缺省函数虽然产生了上述限制,但是相应的能够提高软件整体的可靠性,这将确保所有对象是由定义好的构造函数完整正确的构造得到。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值