2015-10-05 60 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,但不是它指向的内容。