内存泄漏(臭名昭著的Bug):ios
咱们须要什么:安全
解决方案:函数
示例——实现智能指针:ui
#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(3); cout << p1->value() << endl; Pointer p2 = p1; cout << p1.isNull() << endl; cout << p2->value() << endl; return 0; }
运行结果为:this
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out Test(int i) 3 1 3 ~Test()
智能指针的使用军规——只能用来指向堆空间中的对象或者变量spa
再论类型转换:
C语言标准数据类型之间会进行隐式的类型安全转换
C语言转换规则以下:
(C语言编译器支持从小类型(占用内存少)转换到大类型(占用内存多)的隐式类型转换,由于这样的转换是安全的,不会发生数据截断或者数据丢失。)指针
示例——隐式类型转换的bug:code
#include <iostream> #include <string> using namespace std; int main() { short s = 'a'; unsigned int ui = 1000; int i = -2000; double d = i; cout << "d = " << d << endl; cout << "ui = " << ui << endl; cout << "ui + i = " << ui + i << endl; if( (ui + i) > 0 ) { cout << "Positive" << endl; } else { cout << "Negative" << endl; } cout << "sizeof(s + 'b') = " << sizeof(s + 'b') << endl; return 0; }
运行结果为:对象
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out d = -2000 ui = 1000 ui + i = 4294966296 Positive sizeof(s + 'b') = 4
(在大多数编译器看来,int类型,也就是4个字节的整型数的运算是最高效的。而在sizeof(s + 'b')中,是作加法运算,左操做数和右操做数均可以安全的转换为int,那么能够采用更高效的方式来进行运算。因而就出现bug了!)blog
问题:
普通类型与类类型之间可否进行类型转换?
类类型之间可否进行类型转换?
再论构造函数:
旧式的C方式强制类型转换:
编译器会尽力尝试让源码经过编译(普通类型->类类型):
示例——编译器自做聪明的行为:
#include <iostream> #include <string> using namespace std; class Test { int mValue; public: Test() { mValue = 0; } Test(int i) { mValue = i; } Test operator + (const Test& p) { Test ret(mValue + p.mValue); return ret; } int value() { return mValue; } }; int main() { Test t; t = 5; // t = Test(5); Test r; r = t + 10; // r = t + Test(10); cout << r.value() << endl; return 0; }
运行结果为:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out 15
编译器尽力尝试的结果是隐式类型转换。
隐式类型转换:
工程中经过explicit关键字杜绝编译器的转换尝试
转换构造函数被explicit修饰时只能进行显示转换
转换方式:
示例——杜绝编译器的转换尝试:
#include <iostream> #include <string> using namespace std; class Test { int mValue; public: Test() { mValue = 0; } explicit Test(int i) { mValue = i; } Test operator + (const Test& p) { Test ret(mValue + p.mValue); return ret; } int value() { return mValue; } }; int main() { Test t; t = static_cast<Test>(5); // t = Test(5); Test r; r = t + static_cast<Test>(10); // r = t + Test(10); cout << r.value() << endl; return 0; }
运行结果为:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out 15
问题:
类类型是否可以类型转换到普通类型?
类型转换函数:
示例——只有想不到,没有作不到:
#include <iostream> using namespace std; class Test { int mValue; public: Test(int i = 0) { mValue = i; } operator int() { return mValue; } }; int main() { Test t(100); int i = t; // ==> t.operator int() cout << "i = " << i << endl; return 0; }
运行结果为:
[root@bogon Desktop]# g++ test.cpp [root@bogon Desktop]# ./a.out i = 100
类型转换函数:
编译器会尽力尝试让源码经过编译:
类型转换函数 vs 转换构造函数:
示例——能经过编译的类型转换函数:
#include <iostream> #include <string> using namespace std; class Test; class Value { public: Value() {} }; class Test { int mValue; public: Test(int i = 0) { mValue = i; } int value() { return mValue; } operator Value() { Value ret; cout << "operator Value()" << endl; return ret; } }; int main() { Test t(100); Value v = t; // ==> t.operator Value() return 0; }
示例——能经过编译的转换构造函数:
#include <iostream> #include <string> using namespace std; class Test; class Value { public: Value() {} Value(Test& t) {} }; class Test { int mValue; public: Test(int i = 0) { mValue = i; } int value() { return mValue; } }; int main() { Test t(100); Value v = t; // ==> Value(t) return 0; }
示例——冲突的类型转换函数与转换构造函数:
#include <iostream> #include <string> using namespace std; class Test; class Value { public: Value() {} Value(Test& t) {} }; class Test { int mValue; public: Test(int i = 0) { mValue = i; } int value() { return mValue; } operator Value() { Value ret; cout << "operator Value()" << endl; return ret; } }; int main() { Test t(100); Value v = t; return 0; }
报错信息为:
[root@bogon Desktop]# g++ test.cpp test.cpp: In function ‘int main()’: test.cpp:32: error: conversion from ‘Test’ to ‘Value’ is ambiguous test.cpp:21: note: candidates are: Test::operator Value() test.cpp:12: note: Value::Value(Test&)
示例——使用explicit关键字避免冲突:
#include <iostream> #include <string> using namespace std; class Test; class Value { public: Value() {} explicit Value(Test& t) {} }; class Test { int mValue; public: Test(int i = 0) { mValue = i; } int value() { return mValue; } operator Value() { Value ret; cout << "operator Value()" << endl; return ret; } }; int main() { Test t(100); Value v = t; return 0; }