More Effective C++学习记录

注:新手自学,有错误请指正

条款1——引用和指针的区别

定义
指针: 指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元。
引用:引用是一个指向其它对象的常量指针,它保存着所指对象的存储地址。并且使用的时候会自动解引用,而不需要像使用指针一样显式解引用。通俗的说,引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。

区别
1.初始化问题*
指针:既可以在定义时初始化,也可以在后面进行赋值。因此指针指向的对象可以更改。指针还可以初始化为NULL,且指针可以多级使用。
引用:必须在定义时进行初始化且必须是一个已有对象的引用,且一旦初始化后,其指向的对象不可更改。特别注意,不要引用NULL对象,引用只能一级使用。

int *pc = NULL;
int & rc= *pc;`

此时引用的是NULL对象,C++对此没有定义

2.sizeof关键字
指针:sizeof即为一个指针变量的大小,4
引用:sizeof取决于其引用变量的大小,因引用只是个别名

3.参数问题
指针:使用指针时,必须解引用,且必要时必须进行参数检查,因为指针可以指向null
引用:无需使用解引用,直接使用变量即可,且因为引用不能引用null对象,因此不需要进行参数检查。

4.函数返回值问题
如果返回动态分配的对象或内存,必须使用指针,引用可能引起内存泄漏。

5.必须使用引用的地方
运算符重载的时候:对于重载[] = + 必须使用引用,因为如果使用指针就必须通过解引用,与本意不符。例如:

vector<int> v(10);
v[5] = 10;//operator [] 返回 &
*v[5] = 10;//operator [] 返回 *

总结
使用引用条件:
1.指向一个对象,且永远不会改变指向,且对象不为NULL
2.重载几个特殊操作符,[] = +等
3.如果函数入参确保不要被随意更改,可通过const &实现,引用是个别名,运行更快

条款2——使用C++转型操作符

C++支持传统C的类型转换:
在编写C++程序时,一定要优先使用C++的转型操作符。因为C的类型转换存在几个缺点:
1.对于常量和非常量的转换及父类和子类的转换,并没有进行区分。一种只改变对象的常量性,另一种完全改变了对象的类型,C并没有对其详细区分。这对C++不是特别友好。
2.任何类型的转换,C只需要通过()即可以实现,但是C++的转换操作符可以让你明确类型改变的方向,在阅读代码时更方便。

C++转型操作符的简略说明:
1.static_cast
一般来说,编译器隐式执行的任何类型转换都可以由static_cast显式完成。static_cast可以用来将枚举类型转换成整型,或者整型转换成浮点型。也可以用来将指向父类的指针转换成指向子类的指针。
注意,能转换掉expression的const、volatile、或者__unaligned属性,同样也不能用来去掉static属性,且运行时不会进行类型检查,只会强制转换,比较类似C的强制转换
2.const_cast
因为static_cast不会转换对象的const volatile 等易变性和常量性,所以需要const_cast来实现,通过const_cast转换,可以将指定const变量进行改变,但是前提是如果想要修改const变量值需要定义时通过volatile声明,因为去除const属性后,通过指针或引用,可以修改对应const变量内存中的数据,volatile 的作用是取消编译器的优化,每一次使用该内存信息,都很小心地重新读取这块内存的内容。如果没有 volatile, 编译器会采取一些优化,例如把 const 变量拷贝一份放在寄存器中( 或者类似于 cache,这样速率就高 ), 没有 volatile 就意味着,程序一直调用的 const 变量 都是一份拷贝,不仅含有该 const 变量的地址,还含有该 const 变量的信息,不允许修改,但,不是真正的那个内存。真正的内存信息通过 const_cast 改变了,但是一般无法获取到该内存的信息( 因为首先是考虑寄存器中的那份拷贝 )。volatile 就可以重新,稳定地读取该 const 常量真正内存的信息,如果被改变了,也可以得到内存信息

    const int a = 50;
    //a++;  const变量不可更改
    cout<< "a\t="<<a<<"\t&a\t="<<&a<<endl;
    int* p = const_cast<int*> (&a);
    int &r = const_cast<int&>(a);
    //int  d = const_cast<int>(a); const_cast 类型只能是指针或引用
    cout<<"*p\t="<<*p<<"\tp\t="<<p<<endl;
    *p = 100;
    cout<< "a\t="<<a<<"\t&a\t="<<&a<<endl;
    cout<<"*p\t="<<*p<<"\tp\t="<<p<<endl;
    cout<<"r\t="<<r<<"\t&r\t="<<&r<<endl;
    r = 200;
    cout<< "a\t="<<a<<"\t&a\t="<<&a<<endl;
    cout<<"*p\t="<<*p<<"\tp\t="<<p<<endl;
    cout<<"r\t="<<r<<"\t&r\t="<<&r<<endl;

    const volatile int b = 50;
    int* q = const_cast<int*> (&b);
    int& s = const_cast<int&> (b);
    *q = 200;
    cout<< "b\t="<<b<<"\t&b\t="<<&b<<endl;
    cout<<"*q\t="<<*q<<"\tq\t="<<q<<endl;
    cout<<"s\t="<<s<<"\t&s\t="<<&s<<endl;

运行结果:

a       =50     &a      =0x7ffce1631e20
*p      =50     p       =0x7ffce1631e20
a       =50     &a      =0x7ffce1631e20
*p      =100    p       =0x7ffce1631e20
r       =100    &r      =0x7ffce1631e20
a       =50     &a      =0x7ffce1631e20
*p      =200    p       =0x7ffce1631e20
r       =200    &r      =0x7ffce1631e20
b       =200    &b      =1
*q      =200    q       =0x7ffce1631e24
s       =200    &s      =0x7ffce1631e24

特别注意,const_cast只能通过指针和引用来转换 。

3.dynamic_cast
static_cast可以进行父类及子类指针的转换 ,但是不会在运行时进行类型检查,所以在父类指针和子类指针进行转换时,需要使用dynamic_cast,且dynamic_cast必须是父类与子类转换使用,且必须是父类含有虚函数,可以发生多态行为,即dynamic_cast能够在类层次中进行向上转换(类之间是is-a关系),而不允许其他装换。

//动物类
class Animal {
public:
	Animal();
	~Animal();

	virtual void speak() {
		printf("动物在叫!");
	}

private:

};

Animal::Animal() {
}

Animal::~Animal() {
}

//猫类
class Cat :public Animal {
public:
	Cat();
	~Cat();
	virtual void speak() {
		printf("猫在叫!");
	}

};

Cat::Cat() {
}

Cat::~Cat() {
}

//老虎类
class Tiger :public Aniaml
{
public:
	Tiger();
	~Tiger();

	virtual void speak() {
		printf("老虎在叫!");
	}

};

Tiger::Tiger() {
}

Tiger::~Tiger() {
}

int main() {
	Animal* cat= new Cat();
	Animal* tiger = new Tiger();

	Tiger* Tiger1 = dynamic_cast<Tiger*>(tiger);//这是正确的
	Tiger* Tiger2 = dynamic_cast<Tiger*>(cat);//这是错误的


	if (Tiger1 = dynamic_cast<Tiger*>(tiger)) {//正确
		Tiger1->speak();
	}

	if (Tiger2 = dynamic_cast<Tiger*>(cat)){
		Tiger2->speak();
	}
	return 0;
}

4.reinterpret_cast

reinterpret_cast 不具有移植性,尽量不要使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值