2010-04-26 28 views
3

我需要一個像std :: auto_ptr這樣的類來處理一個unsigned char *數組,並用new []分配。但auto_ptr只調用delete而不是delete [],所以我不能使用它。無符號字符數組的自動指針?

我還需要有一個函數來創建並返回數組。我想出了一類ArrayDeleter內我自己的實現,這是我在這個例子中使用,如:

#include <Utils/ArrayDeleter.hxx> 

typedef Utils::ArrayDeleter<unsigned char> Bytes; 

void f() 
{ 
    // Create array with new 
    unsigned char* xBytes = new unsigned char[10]; 
    // pass array to constructor of ArrayDeleter and 
    // wrap it into auto_ptr 
    return std::auto_ptr<Bytes>(new Bytes(xBytes)); 
} 

... 
// usage of return value 
{ 
    auto_ptr<Bytes> xBytes(f()); 
}// unsigned char* is destroyed with delete[] in destructor of ArrayDeleter 

有沒有辦法解決這個問題一個更優雅的方式? (即使使用另一個「流行」庫)

回答

11

Boost有各種自動指針,包括用於數組的指針。你有沒有考慮過std :: vector是否足夠?矢量在內存中保證是連續的,如果你事先知道大小和分配的內存,內存中的位置不會改變。

+0

我看了一下boost,我認爲scoped_array會這樣做。謝謝 – Gianluca 2010-04-26 13:04:34

+3

@Gianluca:你爲什麼不使用矢量? – GManNickG 2010-04-26 14:32:38

+0

@GMan:當然,現在我看到這是一個更好的主意。謝謝 – Gianluca 2010-04-26 15:02:00

2

如何使用std::basic_string<unsigned char>?或者也許std::vector<unsigned char>

+0

然後我必須調用一個將unsigned char *作爲參數的方法。有沒有辦法從你建議的容器中訪問它? basic_string的方法data()會執行嗎? – Gianluca 2010-04-26 13:19:23

+0

你可以使用std :: string'.c_str()'方法,這將返回一個以null結尾的char *。 – Konrad 2010-04-26 14:16:19

3

然後我必須調用一個方法,將unsigned char *作爲參數。

std::vector<unsigned char> vec; 
. 
. 
. 
legacy_function(&vec[0], vec.size()); 
+0

完美,謝謝 – Gianluca 2010-04-26 13:45:12

-1
  1. 你在談論的int一個數組,而不是複雜的C++類型有一個析構函數。 對於這樣一個調用delete[]的數組相當於調用delete。所以使用std::auto_ptr沒有問題。

  2. 你建議的方法是非常野蠻的恕我直言。你實際上分配內存兩次:一次爲所需的數組,然後你還分配一個ArrayDeleter的實例,它將指針封裝到分配的數組中。

這種方法的缺點是:

  • 更糟的性能。堆操作很重。他們也有顯着的內存開銷。
  • 訪問速度較慢。要通過std::auto_ptr<Bytes>訪問數組的元素,編譯器將生成兩個間接符號:一個用於獲取您的對象,另一個用於訪問該元素。 簡單來說:std::auto_ptr有一個指向Bytes的對象,它有一個指向數組的指針。
  • 更糟的錯誤/異常一致性。想象一下,如果operator new未能分配Bytes對象。它會產生一個異常,這可能會被處理。但在這一點上你已經已經分配了數組。這個分配將會丟失。

我會做下列之一:

  1. 如果你談論的是一個普通型 - 只需使用std::auto_ptr<type>。這應該做的工作。但是,你應該使用你的編譯器來檢查它。

  2. 對於複雜類型:您可以創建自己的包裝而不是std::auto_ptr

  3. 另一個變體:類似於你所做的。但是,你應該擺脫額外的內存分配和間接。
+2

在一個動態分配的數組上調用'delete'總是無意義的行爲,即使它在您嘗試的所有編譯器上似乎總是適用。 – fredoverflow 2010-04-26 13:41:46

+0

delete []與調用delete不等同,即使是POD也是如此。參見標準中的18.6.1.2(數組形式):「void operator delete [](void * ptr)throw(); ... 要求:ptr ...應爲先前調用 返回的值operator new [](std :: size_t)或運算符new [](std :: size_t,const std :: nothrow_t&)「 – Francesco 2010-04-26 14:15:22

+0

這正是我寫」你應該用你的編譯器檢查它「的原因。 嚴格來說你是對的。該標準說這是一個未定義的行爲。 OTOH我說什麼*實際*發生。至少在MSVC編譯器上。 應該使用「delete []」而不是「delete」的原因不是因爲我們需要知道應該釋放多少內存 - 根據這個參數,您必須將內存大小傳遞給「free」函數好。 原因是當你使用「delete []」時,除了釋放內存外,編譯器還會生成對象的調用。 – valdo 2010-04-26 14:32:48