首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >引用类型的C++11成员变量,向量push_back后的不同行为

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

Stack Overflow用户
提问于 2015-01-23 19:37:54
回答 2查看 760关注 0票数 16

我正在使用别人的类,当我把它推入一个向量时,它表现得很奇怪。它涉及一个成员变量,该变量是对另一个成员变量的引用。下面是一个最小的自包含示例:

代码语言:javascript
复制
#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. 当对象在向量中时,为什么会有不同的行为?
  2. 为什么g++没有使用c++11标准给出任何关于这方面的警告?

额外的问题,因为我很好奇:

首先初始化的是a还是a_ref

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-23 19:52:29

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

代码语言:javascript
复制
Myclass(const Myclass &src) :
  a(src.a),
  a_ref(src.a_ref)
{}

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

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

票数 16
EN

Stack Overflow用户

发布于 2015-01-23 19:52:56

隐式定义的复制/移动构造函数:

...执行对其基表和成员执行成员级复制/移动。[注意:忽略非静态数据成员的大括号或等于初始值设定项。..。

具体地说,引用成员被直接初始化以引用源对象中的相应引用成员所引用的同一对象。

因此,在您的示例中,vec.at(0).a_ref指的是instance2的成员a

编译器不会检测到这一点,因为通常情况下,引用成员应该引用类外部的较长生存期的对象。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28109083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档