2015-10-05 35 views
0

我對一個類的const引用的理解是我們無法修改該類的狀態,即無法執行任何修改其任何成員變量的操作。但請考慮以下代碼。通過const引用將成員變量複製到類中

#include <iostream> 
#include <vector> 

struct Vec { 
    Vec(std::vector<int>& v) : vec(v) {} 
    Vec(const Vec& v) : vec(v.vec) { 
    v.vec.resize(100); 
    } 

    std::vector<int>& vec; 
}; 

int main() { 
    std::vector<int> x; 
    Vec v1(x); 
    Vec v2(v1); 
    v1.vec.resize(10, 0); 
    v2.vec[5] = 8; 
    std::cout << v1.vec[5] << std::endl; 
    return 0; 
} 

我使用g ++編譯此代碼:4.8.3帶-Wall標誌並編譯。我有兩個問題。

  1. Vec複製建構者,我們傳遞一個const引用到Vec v。通過擴展v的常量,v.vec也應該是const std::vector<int>&。那麼如何將它複製到std::vector<int>
  2. 上述可能發生的唯一合乎邏輯的方式是,類的常量不適用於其成員變量。所以我的問題是一個類的常量對其成員變量有什麼影響?

回答

1
  1. 在VEC副本construtor,我們通過一個常量引用A VEC訴用V的常量性的擴展,v.vec也應該是一個常量的std ::矢量&。那麼它如何被複制到類型std :: vector?
  2. 上述可能發生的唯一合乎邏輯的方式是,類的常量不適用於其成員變量。所以我的問題是一個類的常量對其成員變量有什麼影響?

這不是真的如何擴展。你堅持的類型,而不是前面的 const。請看下面的代碼...

struct foo { 
    foo() {} 

    int * i; 
}; 

int main (void) 
{ 
    foo my_foo; 

    int * &a = my_foo.i; 
    const int * &b = my_foo.i; 
    int * const &c = my_foo.i; 

    const foo const_foo; 

    int * &d = const_foo.i; 
    const int * &e = const_foo.i; 
    int * const &f = const_foo.i; 

    return 0; 
} 

foo.cpp: In function ‘int main()’: 
foo.cpp:12: error: invalid initialization of reference of type ‘const int*&’ from expression of type ‘int*’ 
foo.cpp:16: error: invalid initialization of reference of type ‘int*&’ from expression of type ‘int* const’ 
foo.cpp:17: error: invalid initialization of reference of type ‘const int*&’ from expression of type ‘int* const’ 

這表明const_foo.i具有類型int * const,這是從const int *不同。 int * const類型對其指向的數據沒有改變沒有任何承諾,只是指針本身不能改變。

在您的示例中,v2.vec將具有類型std::vector<int> & const。但是這種類型是沒有意義的(也是非法的),因爲無論如何你都不能改變引用的別名。爲此,std::vector<int>已經是const。


有可能具有常量繼承,但必須明確地編寫該規則。下面的代碼會很樂意拒絕因執行常量限制編譯通過限制呼叫者使用吸氣,讓你正在尋找...

#include <iostream> 
#include <vector> 

struct Vec { 
    Vec(std::vector<int>& v) : _vec(v) {} 
    Vec(const Vec& v) : _vec(v.vec()) { 
     v.vec().resize(100); 
    } 

    // How to make const-ness inherit... 
    std::vector<int> & vec() { return _vec; } 
    std::vector<int> const & vec() const { return _vec; } 

    private: 
    std::vector<int>& _vec; 
}; 

int main() { 
    std::vector<int> x; 
    Vec v1(x); 
    Vec v2(v1); 
    v1.vec().resize(10, 0); 
    v2.vec()[5] = 8; 
    std::cout << v1.vec()[5] << std::endl; 
    return 0; 
} 

一旦你開始這樣做,你進入陌生的領地,不過合同,因爲它允許我調用std::vector<int> const & vec() const,將「數據常量」引用保存爲_vec,然後讓其他代碼更改vec中的數據,將常量合同違反先前的代碼。這裏有很多地雷,這可能就是爲什麼語言沒有內置這種常量繼承的原因。

3

類的常量適用於其成員變量,但不適用於引用成員變量的引用。這與指針成員類似,其中指針將是const,但不是它指向的內容。

相關問題