More Effective C++笔记

item 1:pointers 和references的区别:

1.pointers 不必赋初值,可以指向NULL。references必须赋初值,因为引用是匿名,在初始化的时候必须指名是引用的对象。
因此,如何指向(代表)的对象可以为空,选指针;不为空,选引用。
2.pointers可以被重新赋值,references不可以被重新赋值。
3.重载操作符时,必须返回对象时,用references。例如:<<,[]等

结论:当知道需要指向某个东西,而且绝不会改变其他东西,或是实现一个操作符而其语法需要无法由pointers达成,就该选择references。任何其他时候,请采用pointers。
item 2:最好使用C++的转型操作符

4个新的转型操作符(cast operations):static_cast, const_cast, dynamic_cast, reinterpret_cast

static_cast:用于基本类型的转型
	c:(double)int ,  (int)char
	c++:static_cast<double>int, static_cast<int>char

const_cast:用于改变常量性(constclass Widget {...};
	class SpecialWidge: public Widget {...};
	void updata(SpecialWidget *psw);
	SpecialWidget sw; // sw 是个 non-const 对象
	const SpecialWidget& csw = sw; // csw是个const—reference,引用sw
	update(&csw); //错误!const 类型不能传给 非const类型
	c++:update(const_cast<SpecialWidget*>(&csw));//&csw的常量性被去除,csw引用的对象可以被更改
	c:update((SpecialWidget*)&csw);//效果相同,c旧式转型
	
dynamic_cast:安全的向下转型(缺乏虚函数时或其他转型失败时,抛出异常
	//接上例
	Widget *pw = new SpecialWidget;
	update(pw); // 错误!pw的类型是Widget*,但update()需要SpeialWidget*,需要向下转型
	c:update((SpecialWidget*)pw)
	c++:updata(dynamic_cast<SpecialWidget*>(pw));

reinterpret_cast:转换“函数指针”类型,不具有移植性
(“某些情况下这样的转型可能会导致不正确的结果,所以应该尽量避免将函数指针转型,除非已经走投无路,像是被逼到墙角,而且有一把刀子抵住你的喉咙。一把锐利的刀子,非常锐利的刀子。”)
	略(希望我没有这一天)
item 3:绝对不要以多态(polymorphically)方式处理数组
item 8:了解各种不同意义的new和delete
一.new operator:即常用的new

例如:string *ps = new string(“Memory Management”);
new operator是不能被重载的

这个new operator分为两个动作:
第一,在内存中开出你需要的一片存储空间。
第二,在这片存储空间中,调用构造函数,设定这片空间的初值。

对于第一个动作,可以利用operator new函数来分配一片原生内存空间。
对于第二个动作,我们无法调用一个构造函数。如果就是想要调用某个构造函数,可以稍加修改operator new在一片已经存在的内存中调用一个构造函数,这就是placement new函数。

1.operator new

声明如下:

void * operator new(size_t size);

这个函数返回一个void类型的指针,参数类型为size_t,(sizeof()操作符的返回类型就是size_t),size表示要开的空间大小。
operator new函数可以直接调用也可以用 new operator隐式调用(new operator 调用),直接方式如下:

// 直接调用
void *rawMemory = operator new(sizeof(string)); 
	//	返回一个指针,指向可以一片容纳一个string大小的空间

和c中的molloc一样, operator new只负责分配空间,不调用构造函数。

隐式调用:直接使用new(常用的new),就会调用重载后的operator new函数替换默认的函数。
operator new算符可以重载(这就意味着你可以在分配内存空间的时候就设定初值。)
new的调用动作:

	//当编译器看到如下句子
	string *ps = new string("Memory Management");
	//会产生一下代码,反映一下行为
	void *memory = operator new(sizeof(string));
	// 利用operator new分配内存空间
	
	call string::string("Memory Management") on *memory;
	//将内存中对象初始化

	string *ps = static_cast<string*>(memory);
	// 让ps指向新完成的对象
2.placement new

作用:在已经分配的空间中,调用构造函数,来构造一个对象。
placement new是特殊版本的operator new。其声明看起来如下:

void* operator new(size_t, void *location) {
	return location;
}

具体用法如下:

#include <iostream>

using namespace std;

class A {
    int a;
public:
    A() {
        cout << "A's constructor has been called!" << endl;
    }
    ~A() {
        cout << "A's destructor has been called!" << endl;
    }
    
};

A* constructA(void* buffer) { // placement new
    return new (buffer) A; // 调用placement new
}

int main() {
    void* rawMemory = operator new(sizeof(A));// 利用operator new 分配一片原始空间
    A* a = constructA(rawMemory);//利用placement new构造一个对象
    
    a->~A(); // 调用析构函数
    operator delete(rawMemory); //利用operator delete 回收内存空间
    
    return 0;
}
二.delete operator

同样,我们常用的delete包括两步。1.调用析构函数。2.回收空间
相对应。可以把delete显式的拆成两个语句。如上面例子。先调用析构函数。再利用operator delete (void*)回收一片内存空间。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值