[英]C++ pointers and class member variables confusion
我想知道類成員(屬性)的生命周期是什么。
目前我有這個班:
class Snake {
private:
std::vector<Position> positions = std::vector<Position>();
public:
void addNode(Position * position);
};
我不確定addNode函數是否必須接收指針或對象? 我的猜測是,如果addNode收到一個Position位置作為參數,那么一旦它超出創建的范圍,對象就會死掉,例如
... code here ...
{
Position p = Position(..);
snake.addNode(p);
}
// p should die over here so it could cause a null pointer on the program
另一方面,如果addNode收到一個指針,那么p不會死掉,除非我刪除它(因此它不會導致任何nullpointer),也許你們可以幫助我澄清這個關於我現在的指針的巨大混亂,
謝謝。
對象不需要是指針,但指針是對象。 指針只是一個對象,它存儲一個數字作為某個對象的內存地址。 當指針超出范圍而不會刪除它指向(因此內存泄漏)的對象。
如果您希望您的代碼是最高效和正確的,您應該:
const
引用而不是指針。 如下所示,這將是代碼:
void addNode(const Position& position)
{
positions.push_back(position);
}
void addNode(Position&& position)
{
positions.push_back(std::move(position));
}
它允許避免制作冗余副本並使用const Position
作為參數。 這種方式比其他answears( void addNode(Position position)
)中建議的方式更快,因為它避免了參數的復制到函數中。
當您知道它將超出范圍時,另一個優化是將位置移動到該函數:
{
Position p = Position(x, y);
snake.addNode(std::move(p)); //mind the std::move
} //p will go out of scope here anyway, so it can safely be moved
我們假設addNode
有實現
addNode(Position p){
positions.push_back(p);
}
輸入變量是您傳入的變量的副本。一旦在向量上調用push_back,另一個副本就會在向量內創建,並在向量被銷毀時被銷毀。 此p將被銷毀,但這沒有任何影響,因為vector包含一個副本。 通常,如果編譯器是智能的,它可以避免一些副本,並且可以使用例如std :: move來改進代碼,但我不想為答案添加太多復雜性。
你對“空指針”的評論有點不精確:如果你有一個指針向量,你可以在向量中插入指向p的指針。 如果p超出范圍,指針將懸空,使程序的行為不確定。
不要使用指針,明顯有什么問題?
public:
void addNode(Position position);
問題的關鍵是,雖然position
參數將一次函數退出死了,它的值復制到載體中,並將復印生活在載體,即使原來已經死亡。
這里真的沒有必要指點。
類成員的生命周期與實例相關聯。 它的生命始於構造函數的初始化列表,並在析構函數調用結束時結束。
您似乎認為類是參考值 - 使用C#術語 - 它們不是。 所有C ++對象都是值類型:
{Position p;...}
是Position
類型的對象。 它的構造函數在塊的開頭創建對象,並在結束時調用它的析構函數,這會破壞其內容和對象本身。 {Position* ptr{&p};...}
是Position*
類型的對象。 它的“構造函數”初始化指針。 它的析構函數是無操作但如果它存在則會簡單地破壞它的value = address = number而不是它指向的對象。 指針是另一個對象的地址,在塊的末尾,無論內容是什么,指針都會被銷毀。 就像{int i = 0;}會破壞i
,而不是0
。
{Position& ptr{p};...}
與指針相同的規則。 銷毀引用,而不是引用的對象。
核心思想是指針只是另一種普通的值類型:
Position p;
//Introduces a new name for a type
using Position_p = Position*;
Position_p p1 = &p;
Position_p p2 = p1;
p2++; // Change p2
//p1 is still the same.
int i1 = 5;
int i2 = i1;
i2++; // Change i2
//i1 is still the same.
它們看起來一樣,甚至副本的行為都應該如此。 就像i2
獲得了i1
內容一樣, p2
獲得了p1
內容。 對於int
,內容是一個數字,對於Position_p
它是一個地址。 如果您理解這個概念,那么指針應該變得非常直觀。
所以我的猜測是你想擁有std::vector<Position>
和addNode(Position p)
。 但這會產生不必要的副本,因此addnode(const Position& p)
更好。 你可以在里面做push_back
,並將值復制到向量中。 如果需要,可以使用移動語義來刪除最后一個副本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.