2012-06-16 58 views
1

我是一個java程序員切換到C++。我有一個班級的數據清單。我想返回存儲在類變量中的列表的內容,然後生成一個新列表並將其存儲在類變量中,以便我可以開始將新數據添加到空列表中。我想我知道該怎麼做,但是我想仔細檢查一下,因爲我對引用和C++內存管理很陌生,以後不想再發生內存泄漏。 (注意,我無法輕易複製我的實際代碼,所以我只是重寫它,如果我輸錯了什麼,請原諒我)。確認基本的C++語法

我相信正確的語法將是這樣的:

//mylist is typedef of a list type 
mylist& temporaryList=classList; 
classList=myList(); 
return classList; 

這是語法正確嗎?另外,我是否會隨時擔心釋放返回的變量或classList變量,還是RIAA會爲我處理這些事情?

對不起,問這樣一個簡單的問題,但謝謝你確認我的假設。

+0

我有一個引人注目的猜疑,你可能沒有看太深入指針與引用。請原諒我,如果你有,但[這個問題](http:// stackoverflow。com/questions/57483 /指針變量與參考變量之間的差異在c中)解釋得非常好。 – chris

回答

1

由於@克里斯指出你在那有一個問題,你用的是引用,引用具有很好的功能,他們別名在幾乎沒有成本的實際對象,但在你的情況下,它意味着,當您重置會員列表時,您正在重置程序中的只有列表。

瑣碎天真修復你的代碼,如@克里斯還指出,到複製列表,然後重置原始:現在

mylist getAndClear() { 
    mylist temporaryList=classList; // make a copy 
    classList=myList();    // reset the internal 
    return temporaryList;    // return the **copy** 
} 

,這種方法的問題是,你是當您知道原始列表將立即銷燬時,會產生複製成本。您可以通過使用複製和交換成語(*)避免成本:

MYLIST getAndClear(){ MYLIST TMP; //空 swap(tmp,classList); //交換內容,現在classList爲空 // tmp保存數據 return tmp; }

這是假定myliststd::list。如果不是,請確保您實現了swap(或者在C++ 11移動構造函數中,這將啓用高效的std::swap)。


(*)雖然這似乎不是複製和交換成語的直接應用,它實際上是,在這裏要應用的修改是清除列表。執行副本並對副本進行更改(在這種情況下,可避免副本,因爲更改正在清空副本),然後在操作成功完成後交換內容。

+0

謝謝。我試圖使用別名來避免交換,但是今天回顧一下(而不是在星期五我半睡半醒的時候),這很明顯,爲什麼我的語法錯了。我認爲交換更多... niave是它交換的方式(也就是說,它沒有使用函數指針來避免在列表節點內不理智地複製數據)。現在我認爲這對我來說很愚蠢,我應該已經意識到,像這樣的C函數可以避免在進行交換時不小心的複製。效率是C甚至存在的全部原因。 – dsollen

2
mylist& temporaryList=classList; 

tempraryList是一個參考。當你改變classList時,它也會改變。試試這個:

mylist tempraryList = classList; 

這將複製mylist的複製構造函數,創建一個新的而不是僅僅混淆另一個。


return classList; 

這回你剛剛決定應該是一個新的列表中的一個。你想返回temporaryList。儘管如此,確保它不會被引用返回,因爲temporaryList將超出範圍(清理自己,因爲它被分配到堆棧上),並且最終會產生一個懸掛參考。

通常,不是分配默認構造函數的結果,類可能會提供一種reset函數來實現,而不需要另一個對象的開銷。

0

克里斯提到使用成員函數,這樣的復位或清除對象:

mylist tmp = classList; 
classList.clear(); 
return tmp; 

但你通常可以做的更好,避免在首位的副本。

mylist tmp; 
std::swap(tmp,classList); 
return tmp; 

另外,我會擔心隨時釋放或者返回的變量或班級列表變量或將RIAA照顧這一切給我嗎?

你不需要delete資源,除非你在new他們的某個地方。如果你使用new,那麼你也應該使用智能指針,所以你仍然不需要delete任何東西。

有關C++來自Java的最重要的事情之一就是C++對象默認是類似於值的對象。那就是:

class A { 
    bool bar_called; 
public: 
    A() : bar_called(false) {} 
    void bar() { bar_called = true; } 
    bool has_bar_been_called_on_this_object() { return bar_called; } 
}; 

void foo(A a) { 
    a.bar(); 
} 

int main() { 
    A a; 
    foo(a); 
    std::cout << a.has_bar_been_called_on_this_object() << '\n'; 
} 

輸出將指示杆沒有被封爲a。Java使用,但試圖隱藏,指針。所以一旦你弄清楚C++中的指針應該對你更有意義,然後你將能夠弄清楚如何使用指針而不是

Object o = new Object(); // Java hides the fact that o is a pointer to an Object, but fails to hide the consequences 
Object b = o; // b is a pointer to an object, the same Object o points to. 

// Equivalent C++ 
Object *o = new Object(); 
Object *b = o; 

從C++代碼來看你介紹,在Java中你會做你的詢問像這樣的內容:

mylist tmp = classList; 
classList = new mylist(); 
return tmp; 

在C++中的等效是:

mylist *tmp = classList; // classList is a pointer to a new'd up list. 
classList = new mylist(); 
return tmp; 

但這不是idomatic C++。在C++中,你通常不希望使用指針,如果你想使用智能指針

std::shared_ptr<mylist> tmp = classList; // classList is a std::shared_ptr<mylist> 
classList = std::make_shared<mylist>(); 
return tmp; 

std::unique_ptr<mylist> tmp = std::move(classList); // classList is a unique_ptr 
classList = std::unique_ptr<mylist>(new mylist()); // careful here, don't go calling a bunch of functions inside the mylist initializer, it's dangerous for reason beyond the scope of this post 
return tmp; 

但C++的辦法就是真正完全避免指針。

mylist tmp; // classList is not a pointer at all 
std::swap(tmp,classList); // the values of classList and tmp are swapped 
return tmp; // tmp is returned by value, tmp has the same value as classList, but is not the same object, tmp and classList are objects, not pointers to objects as they are in Java or in the above C++ examples.