一. 智能指针
内存泄漏 (C++ 主要的 Bug 来源)
1. 动态申请堆空间, 用完后不归还
2.C++ 语言中没有垃圾回收机制
3. 指针无法控制所指堆空间的生命周期
代码示例
- #include <iostream>
- #include <string>
- using namespace std;
- class Test
- {
- int i;
- public:
- Test(int i)
- {
- this->i = i;
- }
- int value()
- {
- return i;
- }
- ~Test()
- {
- }
- };
- int main()
- {
- for(int i=0; i<5; i++)
- {
- Test* p = new Test(i);
- cout <<p->value() <<endl;
- }
- return 0;
- }
运行的结果如图所示
可以看出输出结果如预期一样, 但是指针在申请了内存之后没有进行释放, 但当出现大量的数据时, 程序会崩溃
智能指针的需求与目的
1. 需要一个特殊的指针
2. 指针生命周期结束时主动释放堆空间
3. 一片堆空间最多只能有一个指针标识
4. 杜绝指针运算何指针比较
解决方案
1. 重载指针特征操作符 (->)
2. 只能通过类的成员函数重载
3. 重载函数不能使用参数
4. 只能定义一个重载函数
代码示例
- #include <iostream>
- #include <string>
- // 智能指针的实现
- using namespace std;
- class Test
- {
- int i;
- public:
- Test(int i)
- {
- cout <<"Test(int i)" << endl;
- this->i = i;
- }
- int value()
- {
- return i;
- }
- ~Test()
- {
- cout <<"~Test()" << endl;
- }
- };
- class Pointer
- {
- Test* mp;
- public:
- Pointer(Test* p = NULL)
- {
- mp = p;
- }
- Pointer(const Pointer& obj)
- {
- mp = obj.mp;
- const_cast<Pointer&>(obj).mp = NULL;
- }
- Pointer& operator = (const Pointer& obj)
- {
- if( this != &obj )
- {
- delete mp;
- mp = obj.mp;
- const_cast<Pointer&>(obj).mp = NULL;
- }
- return *this;
- }
- Test* operator -> ()
- {
- return mp;
- }
- Test& operator * ()
- {
- return *mp;
- }
- bool isNull()
- {
- return (mp == NULL);
- }
- ~Pointer()
- {
- delete mp;
- }
- };
- int main()
- {
- Pointer p1 = new Test(0);
- cout <<p1->value() <<endl;
- Pointer p2 = p1;
- cout << p1.isNull() << endl;
- cout << p2->value() <<endl;
- return 0;
- }
运行的结果如图所示
可以看到, 指针在在对堆空间使用完之后, 会自动释放内存
小结
1. 指针特征操作符可以被重载
2. 重载指针特征符能够使用对象代替指针
3. 智能指针只能用于指向堆空间中的内存
4. 智能指针的意义在于最大程度的避免内存问题
二. 逻辑操作符的陷阱
A. 逻辑运算符的原生语义
1. 操作数只有两种值 (true 与 false)
2. 逻辑表达式不用完全计算就能确定最终值
3. 最终结果只能是 true 或者 false
代码示例
- #include <iostream>
- #include <string>
- using namespace std;
- int func(int i)
- {
- cout <<"int func(int i) : i =" << i << endl;
- return i;
- }
- int main()
- {
- if( func(0) && func(1) )
- {
- cout << "Result is true!" << endl;
- }
- else
- {
- cout << "Result is false!" << endl;
- }
- cout << endl;
- if( func(0) || func(1) )
- {
- cout << "Result is true!" << endl;
- }
- else
- {
- cout << "Result is false!" << endl;
- }
- return 0;
- }
Q: 逻辑操作符可以重载吗? 重载逻辑操作符有什么意义?
代码示例及结果
- #include <iostream>
- #include <string>
- using namespace std;
- class Test
- {
- int mValue;
- public:
- Test(int v)
- {
- mValue = v;
- }
- int value() const
- {
- return mValue;
- }
- };
- bool operator && (const Test& l, const Test& r)
- {
- return l.value() && r.value();
- }
- bool operator || (const Test& l, const Test& r)
- {
- return l.value() || r.value();
- }
- Test func(Test i)
- {
- cout << "Test func(Test i) : i.value() =" << i.value() << endl;
- return i;
- }
- int main()
- {
- Test t0(0);
- Test t1(1);
- if( func(t0) && func(t1) )
- {
- cout << "Result is true!" << endl;
- }
- else
- {
- cout << "Result is false!" << endl;
- }
- cout << endl;
- if( func(1) || func(0) )
- {
- cout << "Result is true!" << endl;
- }
- else
- {
- cout << "Result is false!" << endl;
- }
- return 0;
- }
可以从代码及运行结果可以看出, 无论逻辑操作符是否更换两端顺序, 都会对两端数据进行运算
B. 问题的本质分析
1.C++ 通过函数调用扩展操作符功能
2. 进入函数体前必须完成所有参数的计算
3. 函数参数的计算次序是不定的
4. 短路法则完全失效
建议: 实际工程开发中避免重载逻辑操作符, 通过重载比较操作符代逻辑操作符重载, 直接使用成员函数代替逻辑操作符重载, 使用全局函数对逻辑操作符重载
小结
1.C++ 从语法上支持逻辑操作符重载
2. 重载后的逻辑操作符不满足短路法则
3. 工程开发中不要重载逻辑操作符
4. 通过重载比较操作符替换逻辑操作符重载
5. 通过专用成员函数替换逻辑操作符重载
来源: http://www.bubuko.com/infodetail-3101753.html