通过const引用将成员变量复制到类

时间:2015-10-05 16:02:45

标签: c++ c++11 copy-constructor

我对类的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;
}

我使用带有-Wall标志的g ++:4.8.3编译了这段代码并进行了编译。我有两个问题。

  1. Vec复制构造函数中,我们将const引用传递给Vec v。通过扩展v的常量,v.vec也应该是const std::vector<int>&。然后如何将其复制到std::vector<int>类型?
  2. 上述唯一合乎逻辑的方法是,如果一个类的常量不适用于它的成员变量。所以我的问题是一个类的常量对它的成员变量有什么影响?

2 个答案:

答案 0 :(得分:3)

类的常量适用于其成员变量,但不适用于作为引用的成员变量的引用。这类似于指针成员,其中指针将是const,但不是它指向的内容。

答案 1 :(得分:1)

  
      
  1. 在Vec copy construtor中,我们将const引用传递给Vec v。通过扩展v的constness,v.vec也应该是 const std :: vector&amp; 。然后如何将其复制到类型std :: vector?
  2.   
  3. 上述唯一合乎逻辑的方法是,如果一个类的常量不适用于它的成员变量。所以我的问题是一个类的常量对它的成员变量有什么影响?
  4.   

这并不是const如何扩展。你将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。

可能有const-ness继承,但您必须显式编写该规则。下面的代码很乐意拒绝编译,因为通过限制调用者使用getter来强制执行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,保存一个&#39; data-const&#39;引用_vec,然后让其他代码更改vec中的数据,违反了与早期代码的const契约。那里有许多地雷,这可能就是为什么语言没有内置这种常量继承的原因。