簡體   English   中英

在 C++ 中,對象和指向對象的指針有什么區別?

[英]in C++, what's the difference between an object and a pointer to an object?

在java和objective-c中,表示對象的變量一般是指向該對象的指針。 但是,在 C++ 中,非指針類型保存對象似乎很常見。 兩者有什么區別?

如果我將一個結構作為參數傳遞給一個函數,我相信我是按值傳遞的,這意味着我實際上是在內存中創建一個新結構,並且在它傳遞給的函數內部對該結構的更改不會影響“源”結構在函數之外。 但是,如果我將一個指針傳遞給一個結構,仍然只有一個原始結構,並且對指針引用的結構的更改將對任何知道該結構的代碼可見。 我有這個權利嗎?

那么,對象有什么區別嗎? 當我將一個非指針對象傳遞給一個函數時,是否會復制整個對象?

跟你說的一模一樣。

當您按值傳遞對象時,將調用其復制構造函數以生成將在函數內部使用的此類對象的新實例。 對此類新對象所做的更改不會反映到原始對象1

與結構一樣,默認復制構造函數只是對原始對象進行淺表復制——即,它的字段被復制2到新實例; 在許多情況下,這是不可取的(例如,如果對象包裝了一個指針/另一個資源),因此有些類會重新定義復制構造函數或完全禁用它。 最后這些類的對象只能通過指針或引用傳遞。

如果對象大於指針(在大小上),或者通常如果它們的復制構造函數不“便宜”,則按值傳遞對象的成本可能很高。 另一方面,與指針相比,按值傳遞具有不必指定指針所有權、讓被調用者對對象做任何想做的事情等通常的優點。

請注意,按值傳遞對象會破壞多態性。 這是因為按值接收對象的函數接收靜態類型對象,具有精確的大小和類型,因此任何傳遞派生類對象的嘗試都將導致對象切片(調用基類的復制構造函數,即默認情況下只復制基類中可用的字段)。

這就是為什么傳遞對象的首選方法通常是通過const引用的原因。 這產生了幾個優點:

  • 不涉及副本; 被調用者將看到的對象將與調用時指定的對象完全相同;
  • 由於const限定符,不能對原始對象進行任何更改;
  • 但是,如果被調用者需要更改對象的副本,它仍然可以根據引用自己構造一個副本;
  • 沒有笨拙的指針語法;
  • 保留了多態性,因為在幕后我們實際上傳遞了一個指針;
  • 對對象所有權毫無疑問:關於引用的一般規則是它們由調用者擁有。

  1. 就對象的“原始字段”而言; 當然,如果原始對象和副本繼續共享指向同一資源的指針/句柄,對其中一個的某些修改可能會影響另一個。

  2. 原始類型(和一般的 POD)按位復制,而復制構造函數被調用用於非 POD 類型。

差異主要與對象在內存中的分配位置有關。 例如:

int main() {
    MyObject x;   //allocates space for an instance of MyObject on the stack
    MyObject* y;  //allocates space for a pointer on the stack
    MyObject* z = new MyObject();  //allocates space for a pointer on the 
                                   //stack and an object instance in the heap and
                                   //sets the pointer to point to the new instance
    MyObject* a = &x;  //allocates space for a pointer on the stack and 
                       //makes it point to 'x'
    ...
}

int someFunc(MyObject byValue, MyObject* byReference) {
   //the 'byValue' parameter will be passed by creating a copy of the 
   //entire source object on the stack (can be quite expensive for 
   //complex object types)

   //the 'byReference' parameter will be passed by creating a 
   //copy of the source pointer on the stack and setting it to 
   //point to the source object in memory
}

在 C++ 中,變量它所代表的變量。 它是內存中的實際對象,位於實際位置。

然而,你可以選擇讓這樣一個變量代表一個指針,在這種情況下它會說“嘿,我是我,我指向那邊,你想要的對象不在這里。它在那里,是的,那里。繼續,到那兒!”。

除非您明確使用 C++ 的“引用類型”(我懷疑您不是),否則您傳遞的所有參數都是按值傳遞的。

第二段和第三段中問題的答案都是“是”。 更具體地說,如果您按值將對象傳遞給函數,該函數將收到該對象的副本(由復制構造函數創建)。

當您按值將對象傳遞給函數時,它會通過其類的復制構造函數進行復制。 如果您沒有定義復制構造函數,編譯器將提供一個默認的復制構造函數(除非您采取特殊步驟來避免這種情況),這相當於手動復制成員。

首選的做法通常實際上是傳遞 const 引用,而不是指針或對象本身。

(您可能想知道,實際上struct只是一個默認情況下其成員是publicclass ;特別是,結構也可以具有用戶定義的復制構造函數。結構不一定只是普通的惰性數據。)

你有那個權利。

確實,這就是它的工作原理。 指針存儲變量的內存地址。

當您將一個指針(指向一個對象)作為參數傳遞給一個函數時,這意味着該函數將可以通過它的內存地址訪問該對象,而不是在堆棧上創建一個新對象。

檢查此線程以獲取有關指針的更多信息。

  • 指針存儲內存地址。
  • 變量存儲一個值。

前任:

Player * a; // Allocated an int value to stored an address, you will able to access to value at that address by a -> but you have to allocated it and free when it done

Player a; // Allocated a block of memory that size equal = Player size.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM