引用类型的 C++11 成员变量, vector push_back 后的不同行为

标签 c++ c++11 vector reference member

我正在使用其他人的类,当我将它插入 vector 时它表现得很奇怪。它涉及一个成员变量,它是对另一个成员变量的引用。这是最小的独立示例:

#include <iostream>
#include <vector>

class Myclass {
public: 
  Myclass() : a(1.0) {}

  float a;
  float &a_ref = a;

  void addOne() {
    a = a + 1.0;
  }
};

int main() {
  Myclass instance1;
  instance1.addOne();

  //prints 2:
  std::cout << "instance.a_ref is " << instance1.a_ref << std::endl;

  std::vector<Myclass> vec;
  Myclass instance2;
  vec.push_back(instance2);

  vec.at(0).addOne();

  //prints 1;
  std::cout << "vec.at(0).a_ref is " << vec.at(0).a_ref << std::endl;
  return 0;
}

我是用g++-std=c++11编译的,所以一时没注意到这个问题。我现在看到问题可能与合成的复制构造函数和引用成员有关。但我不确定的是:

  1. 为什么当对象在 vector 中时会有不同的行为?
  2. 为什么 g++ 没有给出任何警告,使用 c++11 标准?

因为我很好奇,所以有一个额外的问题:

  1. 首先初始化什么,a 还是 a_ref

最佳答案

问题确实出在默认的复制构造函数上。默认的复制构造函数从源对象的成员中初始化所有成员。也就是说,默认的复制构造函数与此相同:

Myclass(const Myclass &src) :
  a(src.a),
  a_ref(src.a_ref)
{}

默认的复制构造函数会初始化所有成员,因此它会忽略任何类内初始化器。

这也是为什么插入 vector 会导致问题。 vec.at(0) 是作为 instance2 的拷贝创建的,这意味着 vec.at(0).a_ref 指的是 instance2.a。您可以通过打印他们的地址 (live example) 轻松验证这一点。

关于引用类型的 C++11 成员变量, vector push_back 后的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28109083/

相关文章:

c++ - 为了避免错误共享,每个单独的 unique_ptr vector 项缓存行对齐的 std::vector<std::unique_ptr<T>> 是否有意义?

c++ - .NET 从具有 www 接口(interface)的打印机获取数据

c++ - 在布局上调整 QGraphicsView 小部件的大小

C++11 for_each 和 lambdas 优化

C++ 使用 std::list of pointers 重新排序 std::vector 元素

c++ - OpenGL 绘制两台计算机之间的差异

c++ - map::emplace 在什么时候创建对象?

C++ - thread_local 变量存储在哪里?

C++ 在 vector 中添加 double 元素

c++ - C++ 中的 vector 不响应一种方法但对其他方法很好