先说一个小发现,在delete []的时候,是按照与构造顺序相反的顺序来析构的!(原来的构造顺序指的是,new []的时候,是按照下标顺序构造的)
#include <iostream> using namespace std; class Log { public: void setId(int id) { this->id = id; } ~Log() { cout << "Destruct " << id << endl; } private: int id; }; int main() { Log* logs = new Log[4]; for (int i = 0; i < 4; ++i) logs[i].setId(i); delete [] logs; return 0; } 12345678910111213141516171819202122232425262728 12345678910111213141516171819202122232425262728上面代码的输出结果为:
Destruct 3 Destruct 2 Destruct 1 Destruct 0 1234 1234据说编译器内部是通过“常量指针”来实现引用的,首先从它的大小来看一下:
#include <iostream> using namespace std; class Log { public: void setId(int id) { this->id = id; } ~Log() { cout << "Destruct " << id << endl; } private: int id; }; struct Wrapper { Log& ref; Wrapper(Log log) : ref(log) {} }; int main() { Log log; Wrapper w(log); cout << sizeof(w) << ' ' << sizeof(log) << endl; return 0; } 1234567891011121314151617181920212223242526272829303132 1234567891011121314151617181920212223242526272829303132输出结果是:8 4
8是一个指针的大小!ps,不能直接通过sizeof(ref)来判断,因为这样会输出4 4,计算的是ref所引用的对象的大小。
下一个主题需要区分指针(类型的)常量和(指向)常量(的)指针,相信看了左边括号里的注释,应该都清楚了吧?
还不清楚,只能po我自己的私藏笔记了:
常量指针,顾名思义,就是指向一个常量的指针,比如:
const int id = 555; const int* p1 = &id; int const* p2 = &id; *p1 = 233; // 错误!不允许通过指针修改变量的值,因为指向的是常量 int hello = 666; p1 = p2 = &hello; // 可以给指针重新赋值,指针本身不是常量 12345678 12345678它的特点是,不能通过指针去修改所指向变量的值,常用于函数传参时声明变量内容不允许被修改(当然也可以用常引用)。
xx常量指的是这个变量是一个常量,不能修改其值,所以,“指针常量”指的就是这样的形式:
int id = 233, id2 = 555; int* const p = &id; id = 666; p = &id2;// 错误!p是一个常量,不允许修改它的值 p = &id;// 错误!这样也不行,不要以为p的值等于&id就可以给它赋值,哼╭(╯^╰)╮ 12345 12345你可以修改原始变量的内容(只要它不是const修饰的),但是不能改变指针的值,也就是说,这个指针就只能被指定为指向这个变量了!
据说,编译器内部用常量指针来实现引用!(只是传言而已)
直接po代码,代码清晰得,都不用解释的^_^
#include <iostream> #include <vector> #include <set> #include <map> #include <algorithm> #include <string> using namespace std; class Log { public: Log(int n) : id(n) {} Log& operator = (const Log& rhs) { id = rhs.id; return *this; } void display() const { cout << "Log " << id << endl; } private: int id; }; template<typename T> class Reference { private: /* 使用“指针常量”来模拟引用的行为: 1) 只能绑定一个变量; 2)必须在初始化才能使用; 3)后续的所有赋值都是改变所绑定的变量的值。 至于为什么是指针常量,是因为要求,这个指针不能改为指向别的变量! */ T* const pointer; public: Reference(T& object) : pointer(&object) {} T& operator = (T& object) { return *pointer = object; } }; int main() { Log test(233); test.display(); Reference<Log> ref(test); Log test2(666); ref = test2; // 通过引用改变所绑定的值 test.display(); return 0; } 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162输出结果是:
Log 233 Log 666