跳轉到內容

C++ 程式設計/運算子/指標/智慧指標

來自華夏公益教科書,開放的書籍,面向開放的世界

智慧指標

[編輯 | 編輯原始碼]

使用原始指標儲存分配的資料,然後在解構函式中清理它們,通常被認為是一個非常糟糕的想法,因為它容易出錯。 即使將分配的資料暫時儲存在原始指標中,然後在完成操作後刪除它,也應該出於這個原因避免這樣做。 例如,如果您的程式碼丟擲異常,正確捕獲異常並刪除所有分配的物件可能很麻煩。

智慧指標可以透過使用編譯器和語言語義來確保指標內容在指標本身超出範圍時自動釋放,從而緩解這種頭痛。

#include <memory>
class A
{
public:
        virtual ~A() {}
	virtual char val() = 0;
};

class B : public A
{
public:
	virtual char val() { return 'B'; }
};

A* get_a_new_b()
{
	return new B();
}

bool some_func()
{
	bool rval = true;
	std::auto_ptr<A> a( get_a_new_b() );
	try {
		std::cout << a->val();
	} catch(...) {
		if( !a.get() ) {
			throw "Memory allocation failure!";
		}
		rval = false;
	}
	return rval;
}


Clipboard

待辦
可以注意到分配器使用的 rebind 模式是使用模板模板引數的替代方法。 從歷史上看,STL 在 C++ 編譯器提供對模板模板引數的支援之前就已基本開發完畢。 有趣的是,現代模板超程式設計風格提倡了一種類似於 rebind 的方法,而不是使用模板模板引數。


auto_ptr 具有嚴格所有權的語義,這意味著 auto_ptr 例項是負責物件生命週期的唯一實體。 如果複製一個 auto_ptr,源將丟失對該引用的引用。 例如

#include <iostream>
#include <memory>
using namespace std;
 
int main(int argc, char **arv)
{
    int *i = new int;
    auto_ptr<int> x(i);
    auto_ptr<int> y;
    
    y = x;
    
    cout << x.get() << endl;
    cout << y.get() << endl;
}

此程式碼將列印第一個 auto_ptr 物件的 NULL 地址,以及第二個的某個非 NULL 地址,這表明源物件在賦值期間(=)丟失了對該引用的引用。 示例中的原始指標 i 不應該被刪除,因為它將由擁有該引用的 auto_ptr 刪除。 事實上,new int 可以直接傳遞到 x 中,從而消除了對 i 的需要。

請注意,由 auto_ptr 指向的物件使用 operator delete 銷燬;這意味著您應該只對使用 operator new 獲得的指標使用 auto_ptr。 這不包括由 malloc()calloc()realloc()operator new[] 返回的指標。

華夏公益教科書