2013-06-21 37 views
0

我有利用的std ::修飾符Modifiers像這樣一類:如何禁止或阻止堆棧分配變量的傳遞?

void Foo::AddBar(Bar* _bar) 
{ 
    Bars.push_front(_bar); 
} 

void Foo::DeleteBar(Bar* _bar) 
{ 
    for (forward_list::iterator index = Bars.begin(); index != Bars.end(); ++index) 
    { 
    if (_bar == *index) 
    { 
     delete _bar; 
     forward_list.remove(_bar); 
    } 
    } 
} 

如果我通過一個棧分配的變量,在調試/釋放它會給我一個運行時錯誤,在生產中,將「撕裂」了堆。

Bar bar; 
foo.AddBar(&bar); 
foo.DeleteBar(&bar); // Memory corruption on "delete _bar" 

如何防止Foo :: AddBar接受堆棧分配的數據?有沒有更好的方法來設計這個?


編輯 13年6月21日

含內部的delete _bar;forward_list.remove(_bar); for循環,導致運行錯誤迭代增量時。

我選擇保​​持控股權完全在Foo和使用模板,像這樣:

template<class T> T* AddBar() 
{ 
    Bar* object = new T(); 
    Bars.push_front(object); 
    return object; 
} 
// Usage looks like... 
Process* pid = foo.AddBar<MyBar>(); // adding a subclass of Bar 

我使用的指針作爲PID - 用於查找目的。我總是可以返回int以防止用戶從delete未經首先投射。哦,和論據我能做AddBar(void* arguments)

+0

「禁止[UB]」。在C/C++中?哈哈哈。 – user2246674

+0

您不能簡單地將指針(或引用)存儲到局部變量。你必須存儲副本。 –

+0

你可以採取像boost :: shared_ptr 這樣的輸入,而不是原始指針。 – Dan

回答

2

簡單的說,你不能。指針是一個指針。你應該首先避免它們。如果您選擇使用它們,請創建一份文檔政策並對代碼進行適當審查。

在所有權的轉移如發生(或至少一半的東西設計的一部分也太臭),您必須證明。該函數只能用特定方式創建的對象調用。 &欄必須被視爲違反該評論。

+0

_「指針是一個指針,你應該首先避免它們。」_我發現這樣的總括性語句是可怕的建議。選擇強/智能指針當然是一個好主意,但是在適當的時候可以並且應該使用「原始指針」。一套寫得很好的編碼準則將包括原始指針和引用的生命週期和所有權語義。原始指針還允許您指示值爲_optional_ where - 作爲引用不能,因爲在C++中沒有這樣的空引用。 –

+0

這將是毯子,如果停止後右邊有 –

+0

「你必須證明」和「必須在審查中招」傷了我的預期功能。具體而言,這是微控制器上樣板代碼的封裝。意思是,如果它錯過了評論,它將很難調試。 +1的真相! –

1

更改接口和實現使用unique_ptr

雖然用戶仍然可以包裝自己的堆棧指針在unique_ptr,它至少是明顯的,這是存在的。

struct Foo { 
    typedef std::vector< std::unique_ptr<Bar> > bar_storage; 
    bar_storage bars; 
    Bar* AddBar(std::unique_ptr<Bar>); 
    void DeleteBar(Bar* bar); 
}; 
void Foo::AddBar(std::unique_ptr<Bar> bar) 
{ 
    Bars.push_back(std::move(bar)); 
} 

void Foo::DeleteBar(Bar* bar) 
{ 
    for (bar_storage::iterator index = Bars.begin(); index != Bars.end(); ++index) 
    { 
    if (bar == *index) 
    { 
     Bars.erase(index); 
    } 
    } 
} 

我做了什麼推未定義行爲來調用網站,特別是:

Bar bar; 
foo.AddBar(&bar); // does not compile 

相反,主叫方被迫:

foo.AddBar(std::unique_ptr<Bar>(&bar)); // user just did something really vulgar! 
foo.DeleteBar(&bar); // Memory corruption on "delete _bar" 
特別

,因爲您foo代表Bar所有權時,應僅由ALRE的代碼來完成的BarFoo加入ady擁有Bar。表示這種單一所有制的std::unique_ptr<Bar>所有回創作方式,以及那些你必須刪除右邊是unique_ptr,而那些你不知道是Bar*

+0

我會試一試。我也隱約記得一些使用句柄和工廠方法的pascal代碼(mac 7),也可以試試。 –