2010-10-08 242 views
26

如果已經提出了這個問題,我表示歉意,但是如何在C++中創建一個成員函數來返回以下場景片段中的指針: 1.返回的指針是常量,但裏面的垃圾可以修改。 2.裏面的垃圾是固定的,但返回的指針可以修改。 3.既不能修改垃圾也不能修改指針。C++ const成員函數返回一個const指針..但是返回的指針是什麼類型的const?

是不是像這樣:

  1. int *const func() const
  2. const int* func() const
  3. const int * const func() const

所有我讀過並不包括這種區別的教程。

附註: 如果我的方法被聲明爲const,那麼教程會說我說我不會修改這些參數..但是在參數是指針的情況下,這對我來說還不夠清楚。我的參數需要如下:

a。 b。 void func(const int* x) const;
c。 void func(const int* const x) const;

+0

組合意識到const成員funcs中什麼都沒有做修改參數,但更多的有關修改類變量。 – Jor 2010-10-08 08:02:35

回答

53

我不知道是什麼書你讀過,但如果你標記的方法常量就意味着thisconst MyClass*型的,而不是MyClass*,這反過來意味着你不能改變非靜態數據成員是沒有聲明mutable,您也不能在this上調用任何非常量方法。

現在爲返回值。

1。 int * const func() const

該函數是不變的,返回的指針是常量,但'垃圾裏'可以修改。但是,我看到返回一個常量指針,因爲最終的函數調用將是一個右值,和非類類型的右值不能被const,這意味着const無論如何都會被

2忽略不點。 const int* func() const

這是一件有用的事情。 「垃圾箱內」不可修改

3。 const int * const func() const

語義上幾乎一樣2,由於在1

到原因HTH

+1

我認爲你在這個回覆中有一些有用的信息,但我的問題仍然存在。如果我使用const方法創建成員方法,那麼我需要*作爲我的方法簽名。我很抱歉,如果我不理解你 – Jor 2010-10-08 07:42:03

+1

@Jor:你不需要對函數簽名的其餘部分做任何限制。唯一需要注意的是,在一個'const'方法中'this'是一個指向'const'的指針,所以如果你通過指針或引用返回一個成員,那麼任何一個返回值都必須是引用或指向'const'類型的指針或者你將不得不做一個有潛在危險的'const_cast'。 – 2010-10-08 07:48:50

+1

@Jor:也就是說,返回類型取決於你返回的內容。如果您要返回類成員的地址,那麼該成員在const成員函數內是const的,所以您需要選項(2)。 – 2010-10-09 23:14:46

9

常量的某些用途並不真的太大的意義。

假設你有以下功能:

void myFunction (const int value); 

的常量告訴數值不能在函數內部改變編譯器。該信息對於調用者沒有任何價值。這取決於函數本身來決定如何處理值。對於來電,下面的兩個函數定義的行爲如出一轍他:

void myFunction (const int value); 
void myFunction (int value); 

因爲值是按值傳遞,這意味着該函數獲取本地副本反正。

另一方面,如果參數是一個引用或指針,事情會變得非常不同。

void myFunction (const MyClass &value); 

這告訴值是通過引用傳遞調用者(所以屏幕背後實際上是一個指針),但主叫方承諾不改變價值。 也是一樣的指針:

void myFunction (const MyClass *value); 

我們通過一個指向MyClass的(由於性能原因),但該功能保證不變的價值。

如果我們這樣寫:

void myFunction (MyClass * const value); 

然後我們又回到詮釋他的第一種情況。 myFunction獲取一個指針,該指針通過值傳遞,並且是const。由於MyFunction獲取指針值的副本,因此調用者無論是否爲const都無關緊要。最重要的是myFunction可以改變值的內容,因爲指針變量本身是const的,但其中的內容不是。

同樣是真實的返回值:

const double squareRoot(double d); 

這沒有任何意義。 squareRoot返回一個const double,但由於這是通過'值'傳遞的,因此需要被複制到我自己的局部變量中,我可以隨心所欲地做任何事情。

在另一方面:

const Customer *getCustomer(char *name); 

告訴我,GETCUSTOMER我返回一個指向一個客戶,而我不能改變客戶的內容。

其實,這將是更明智的字符指針,內容常量爲好,因爲我不希望功能改變給定的字符串:

const Customer *getCustomer(const char *name); 
+0

好吧,我開始理解帕特里克,並且我意識到const方法與不修改類成員有關。因此,請忘記這一點。但我喜歡你的答案,所以也許你可以回答這些問題:在「const Customer * getCustomer(char * name);」你說調用者不能修改結果。但是,他們不能通過返回的變量修改結果,但是如果他們將該指針複製到另一個指針,他們*可以*修改內容? – Jor 2010-10-08 08:00:15

+0

這是另一個問題。一個const方法不能返回一個指向它的類成員的指針,除非它是一個const指針..但是它必須是什麼類型的const指針呢? 1:const * int 2:const * const int 3:int * const – Jor 2010-10-08 08:04:34

+0

如果將「const Customer * getCustomer()」函數的返回值賦值給「Customer *」變量,那麼您將能夠更改客戶的內容。然而,C++編譯器在這個賦值中給出了一個錯誤,因爲你通常不允許給一個非常量指針指定一個常量指針,因爲這賦予了你「附加權限」(即:能夠改變顧客)。然而,在某些情況下(尤其是在處理較舊的純C代碼時),您可能需要繞過這一點,然後您應該使用const_cast。 – Patrick 2010-10-08 08:05:52

0

的常量方法阻止您修改成員。在指針的情況下,這意味着你不能重新分配指針。你可以修改指針所指向的對象,使其指向你心中的願望。

由於指針是由值(副本)返回的,因此調用者不能使用它來修改類的指針成員。因此,將const添加到返回值中什麼也不加。

如果您要返回指針的引用,則情況會有所不同。現在,如果指針不是const,這意味着一個沒有修改值的權限的函數將這個權限授予調用者。

例子:

class X 
{ 
    int* p; 
public: 
    int* get_copy_of_pointer() const //the returned value is a copy of this->p 
    { 
     *p = 42; //this being const doesn't mean that you can't modify the pointee 
     //p = 0; //it means you can't modify the pointer's value 
     return p; 
    } 
    int* const& get_reference_to_pointer() const //can't return a reference to non-const pointer 
    { 
     return p; 
    } 
}; 
1

返回一個指針爲const使得有很大的意義,而是返回一個常量指針(不能修改),通常沒有任何價值(雖然有人說這可以防止用戶錯誤或添加編譯優化)。

這是因爲返回值屬於函數的調用者,即它是他們自己的副本,因此如果他們修改它(並指向別的東西)並不重要。然而,內容不屬於調用者,並且該功能的實現者可以簽約它是隻讀信息。

Const成員函數保證不改變類的狀態,儘管這不一定是編譯器實際執行的。我在這裏不是指const_cast或mutable成員,而是因爲如果你的類本身包含指針或引用,const成員函數會將你的指針變成常量指針,但不會使它們成爲指向const的指針,類似地,你的引用不會變成到const的引用中。如果這些是你的類的組件(並且這些組件通常由指針表示),那麼你的函數可以改變它們的狀態。

可變成員有利於讓您的班級在不改變內部狀態的情況下更改班級。這些通常可以應用於:

  • 您希望鎖定甚至讀取的互斥鎖。
  • 延遲加載的數據,即在第一次訪問它們時填充的數據。
  • 引用計數的對象:如果它需要另一個查看器,則需要增加引用計數,因此您只需修改它的狀態即可讀取它。

const_cast通常被認爲是「黑客」,並且通常在其他人沒有正確編寫代碼的情況下完成。它可在下列情況下,雖然具有價值:

  • 多個重載,其中一個是常量和一個非const和const返回一個const引用和非const返回一個非const引用,但在其他方面他們是一樣的。複製代碼(如果它不是一個簡單的數據成員獲取)不是一個好主意,所以實現一個代碼並使用const_cast來繞過編譯器。

  • 你想特別地調用const超載,但有一個非const引用。首先將其強制轉換爲const。

4

int *const func() const

你不能在這裏觀察const除少數情況下

  • 考慮的func地址。
  • 在C++ 0x中,將函數調用語法直接調用func作爲decltype操作數,將產生int * const

這是因爲你返回一個純指針值,也就是說一個指針值實際上並不存儲在指針變量中。這些值不是常數限定的,因爲它們無論如何都不能改變。即使您拿走const,也不能說obj.func() = NULL;。在這兩種情況下,表達式obj.func()具有 類型int*並且是不可修改的(有人很快會引用標準並提出術語「右值」)。

因此,在上下文中,您使用返回值,您將無法計算出差異。就在你引用聲明或整個函數本身的情況下,你會注意到它們之間的差異。

const int* func() const

這是你如果身體會像return &this->intmember;通常會做什麼。它不允許通過執行*obj.func() = 42;來更改int成員。

const int * const func() const

這僅僅是前兩個:)

相關問題