簡體   English   中英

了解const

[英]Understanding const

如果要編寫迭代器,通常會寫

T* operator->() const;

我的問題是通過指針和引用來理解此“ 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 ++和clang中)。 為什么?

如我所定義

const A a{x};

這個“ a”是常量。 所以當我打電話

int* p = a.ptr();

我正在使用const對象調用ptr(),因此內部指針A-> x必須為“ int * const”。 但是我返回的是沒有const的“ int *”。 為什么這是正確的?

參考會發生什么? 如果我用“ const A”調用A :: ref(),此函數返回的類型是什么? 像“ int&const”之類的東西??? <---我想這與“ int&”相同。

謝謝你的幫助。

按位const和邏輯const之間有區別。

當您擁有const A ,您將無法修改其int*成員。 但有修改構件本身之間的差( intx點),並通過構件(的值修改intx點)。 那些是不同種類的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;}
//  ^^^^^

現在,用戶既不能按位(不能更改x指向的內容)又不能通過邏輯上(也不能更改該指針的值)通過const A修改。

但是為什么它可以編譯並正確運行(至少在g ++和clang中)。 為什么?

因為程序格式正確,並且定義了行為。 沒有違反常量正確性。

我正在使用const對象調用ptr(),因此內部指針A-> x必須為“ int * const”。 但是我返回的是沒有const的“ int *”。 為什么這是正確的?

因為完全可以復制const對象。 這些副本不必是const。 復制對象不會對原始對象進行修改(假設沒有用戶定義的復制構造函數會執行愚蠢的操作)。

參考會發生什么? 如果我用“ const A”調用A :: ref(),此函數返回的類型是什么?

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

像“ int&const”之類的東西???

沒有像int& const這樣的東西。 引用不能具有頂級限定符(永遠不能重新分配它們)。

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 to不是常數 ,這意味着沒有什么可以阻止您編寫如下內容:

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來重載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

暫無
暫無

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

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