內存泄漏(臭名昭著的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; }