C++11 引用类型的成员变量,向量push_back后的不同行为
C++11 member variable of reference type, different behaviour after vector push_back
我正在使用别人的类,当我把它推到向量中时,它表现得很奇怪。它涉及一个成员变量,该成员变量是对另一个成员变量的引用。下面是最小的自包含示例:
#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
进行编译,所以我有一段时间没有注意到这个问题。我现在看到问题可能与合成的复制构造函数和引用成员有关。但我不确定的是:
- 为什么当对象在向量中时会有不同的行为?
- 为什么
g++
没有给出任何警告,使用 c++11 标准?
奖励问题,因为我很好奇:
- 首先初始化什么,
a
还是a_ref
?
问题确实出在默认的复制构造函数上。默认的复制构造函数初始化源对象成员中的所有成员。也就是说,默认的复制构造函数与此相同:
Myclass(const Myclass &src) :
a(src.a),
a_ref(src.a_ref)
{}
默认的复制构造函数初始化所有成员,因此它会忽略任何类内初始化器。
这也是为什么推入矢量会导致问题的原因。 vec.at(0)
是作为instance2
的副本创建的,这意味着vec.at(0).a_ref
指的是instance2.a
。您可以通过打印他们的地址(实时示例)轻松验证这一点。
隐式定义的复制/移动构造函数:
[...]执行其基和成员的成员复制/移动。[ 注意:忽略非静态数据成员的大括号或等于初始值设定项。[...]
特别是,引用成员被直接初始化为引用源对象中的相应引用成员引用的同一对象。
所以在你的例子中,vec.at(0).a_ref
指的是instance2
的成员a
。
编译器不会检测到这一点,因为在一般情况下,引用成员应引用类外部生存期较长的对象。
相关文章:
- 推导 std::vector::back() 的返回类型
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- vector.push_back(vector.back()+1) 是未定义的行为吗?
- C++自己的对象堆栈.在 push() 上复制了什么?
- C++ push() 和 pop() 方法使用指针的动态 LinkedList 的问题
- 如何像在javascript中一样"push" c ++映射
- 线路抑制状态错误 C4703 可能未初始化的局部指针变量"back"已使用
- std::vector using back(), pop_back(), push_back(), 得到'double free or corruption'错误
- vector.back()和vector.end()有什么区别
- 列表大小为 1,但 front() 和 back() 不相等
- 返回C++中没有 back() 方法的容器的最后一个元素?
- 在非空 std::list 上使用 std::list.back<int>() 时"Segmentation Fault"
- 模板堆栈类的复制构造函数中的 pop() 和 push() 不起作用
- 我们可以使用Back() - 值索引在其上执行向量插入
- 当我运行以下代码添加str.front() str.back时,它给了我200个,但为什么
- push(ing)back在循环中对象指针
- 在 C++ 中将元素添加到空向量:为什么 push.back 有效而 [] 无效
- 我似乎无法让 v.push.back() 处理字符串
- String::push_back() does not push back
- 向量resize(), push.back(), reserve()方法