2017-08-28 47 views
1

如果你想要寫一個迭代器,你平時寫瞭解常量

T* operator->() const; 

我的問題是理解這一「常量」與指針和參考。

例如,你可以寫下面的結構:

struct A{ 
    int* x; 

    A(int& x0):x{&x0}{} 
    int* ptr() const {return x;} 
    int& ref() const {return *x;} 
}; 

你也可以使用這種方式:

int x = 10; 
const A a{x}; 

int& r = a.ref(); 
int* p = a.ptr(); 

*p = 4; 
cout << x << endl; // prints 4 

r = 25; 
cout << x << endl; // prints 25 

但爲什麼這個編譯和作品的權利(至少g ++以及鐺)。爲什麼?

正如我所定義

const A a{x}; 

此 「a」 是常數。所以,當我打電話

int* p = a.ptr(); 

我打電話PTR()的const對象,因此內部指針A-> x必須爲 「int * const的」。但是我沒有const返回一個「int *」。爲什麼這是正確的?

而參考文獻會發生什麼?如果我用「const A」調用A :: ref(),那麼這個函數返回的類型是什麼?像「int & const」之類的東西? < ---我想這跟「int &」是一樣的。

感謝您的幫助。

+3

你可以隨時複製一個常量。 – molbdnilo

回答

10

按位const和邏輯const有一個不同。

當您有const A時,您不能修改其成員int*。但是修改成員本身(其中intx指向)並通過成員修改(x指向的int的值)之間存在差異。這些是const的不同種類。最簡單的例子:

struct Ptr { int* p; }; 

int i = 42; 
const Ptr ptr{&i}; 
*ptr.p = 57; 

ptr.p仍指向i,沒有發生變化,因此,所以const技工執行。但這不是邏輯const,因爲您仍然通過const對象更改了某些內容。儘管如此,該語言並沒有強制執行。這取決於你作爲圖書館作家。

如果你想傳播const -ness,你只需要提供一個接口,在邏輯上是const

int const* ptr() const {return x;} 
int const& ref() const {return *x;} 
// ^^^^^ 

現在,用戶無法通過您的const A都按位修改(不能改變什麼x指向)並且在邏輯上(不能改變該指點者的那個值)。

2

struct A,當你對它const一個實例,你讓指針常量,但不會自動使指向的對象不變

聲明類似const A a(ref);基本上等同於調用下面的代碼:

struct A_const { 
    int * const x; 

    A(int& x0):x{&x0}{} 
    int* ptr() const {return x;} 
    int& ref() const {return *x;} 
}; 

如果你還記得你的指針的規則,這意味着x是一個常量指針,這意味着它不能做出點東西其他(它的功能類似於一個參考,但可以null),但重要的是,int,它是指向不恆定,這意味着沒有什麼可以阻止你寫的東西是這樣的:

int val = 17; 
const A a(val); 
*(a.val) = 19; //Totally valid, compiles, and behaves as expected! 
int val2 = 13; 
//a.val = &val2; //Invalid, will invoke compile-time error 

這也是爲什麼std::unique_ptr<int>std::unique_ptr<const int>代表不同的對象。

如果您希望指向對象在const對象上不可修改,則需要在代碼本身中強制執行該操作。由於功能可以在源對象是否是const與否的基礎上超載,這是相當容易:

struct A { 
    int * x; 

    A(int& x0):x{&x0}{} 
    int * ptr() {return x;} 
    int & ref() {return *x;} 
    int const* ptr() const {return x;} 
    int const& ref() const {return *x;} 
}; 

int val = 17; 
A a(val); 
a.ref() = 19;//Okay. 
*a.ptr() = 4;//Okay. 

const A b(val); 
b.ref() = 13;//Compile error 
*b.ptr() = 17;//Compile error 
3

但爲什麼這個編譯和作品的權利(至少g ++以及鐺)。爲什麼?

由於該程序結構合理,並具有定義的行爲。不違反正確性。

我用一個const對象調用ptr(),所以內部指針A-> x必須是「int * const」。但是我沒有const返回一個「int *」。爲什麼這是正確的?

因爲複製const對象是完全可以的。這些副本不需要是const。複製對象不會對原始對象進行修改(假設沒有用戶定義的複製構造函數執行傻事)。

這個參考會發生什麼?如果我用「const A」調用A :: ref(),那麼這個函數返回的類型是什麼?

int& ref()總是返回int&。就像int* ptr()總是返回int*

類似於「int & const」?

有沒有像int& const這樣的事情。引用不能有頂級限定符(它們永遠不能被重新賦值)。

+1

你從哪裏看到複印件正在製作? 'ref()'和'ptr()'都返回一個非const引用或指向成員變量的指針。由於該對象是const,因此以這種方式修改其成員可能會導致未定義的行爲。 –

+1

@MarkRansom既不返回一個引用或指向成員變量的指針。 'ptr'返回成員變量的一個*副本(這是我看到一個副本的地方;另一個副本是在'p'的初始化中,該函數的返回值),'ref'返回一個對由成員變量。您不能使用這些功能修改成員。我在代碼中看不到UB。 – user2079303

+0

好吧,我明白你的觀點 - 這是我最後的一個閱讀理解問題。我很困惑於間接的層次數量。由於'int x = 10'是* not * const,並且對象保持一個指向該外部變量的指針,所以沒有未定義的行爲。 –