【发布时间】:2020-06-24 05:18:48
【问题描述】:
首先我认为以下绝对是未定义的行为:
Object & foo(){
Object o;
return o;
}
Object & ref = foo();
但是现在假设一个函数引用另一个将存在更长时间的对象,并将该引用分配给局部变量,并且局部变量超出范围。这个对象的引用是否也会随着局部变量的销毁而被销毁?
class b {
public:
int val;
b& round() {
val += 2;
return *this;
}
int operator+(int i) const{
return val + i;
}
};
template<typename T>
class A {
public:
typedef typename std::vector<b>::const_reference const_reference;
typedef typename std::vector<b>::reference reference;
vector<b> _a;
A() {
_a.resize(10);
}
inline const_reference set() const {
return _a.at(0);
}
inline reference set() {
return _a.at(0).round();
}
};
void func1(A<int>& a) {
b tmp = a.set();
tmp.val = tmp.val + 2;
cout << a._a[0].val << endl;
}
int main() {
A<int> a;
a.set();
func1(a);
cout << a._a[0].val << endl;
}
对_a[0] 的引用基本上分配给func1 中的tmp。
我这样做是因为我担心_a[0] 会因为tmp 超出范围而被破坏,但是我想返回一个引用以便我可以将它用作左值,将右值直接分配给它,喜欢做
a.set() = 1;
还有一点是我不得不写另一个set() const函数并返回一个const引用。
我不得不在另一个set 中编写const 关键字,因为在另一个函数中,例如func2,我将输入作为const vector 引用传递,但我的用法并没有修改它。但是,如果没有 set() const 方法,编译器会在调用 func2(输入、输出)时出错。
没有匹配函数调用'const vector类型的对象。参数的类型为const,但方法未标记为const。
void func2(const vector<A>& input, vector<A>& output) {
int sum = input[0].set() +2;
}
对我来说,涉及const 规则的事情变得非常棘手。所以为了解决这种情况,我想先把input[0].set()复制到本地的tmp,再做加法。
所以回到原来的问题:
包含引用的局部变量会在超出范围时破坏引用本身吗?即b tmp = a.set(); 当tmp 超出func1 的范围时,a 或a._a[0] 或a._a[0] 上的任何更改也将被释放,因为tmp 是对a._a[0] 的引用?
请原谅我太冗长了...当我知道并尝试学习模板编程和 C++ 的常量时,事情变得非常复杂和艰难...所以我试图灵活地有时使用@987654349 @ 作为左值赋值的参考,有时我也想将它用作右值。
【问题讨论】:
-
Basically reference to _a[0] is assigned to 'tmp' in func1. I am doing it this way because I have concerns that _a[0] would be destroed as tmp goes out of scope,这个说法很好奇。首先,仅仅因为一个对象被破坏并不意味着它被复制或引用的对象也被破坏。其次,即使您担心tmp被销毁会对_a[0]产生影响,那您为什么还要使用tmp? -
“引用被破坏”是无意义的术语
-
你的程序看起来不错,我不清楚问题到底是什么
-
"首先我认为下面肯定是 UB。" 实际上不是,如果从未使用过
ref。简单地绑定一个无效的引用不是 UB。 使用无效的引用是 UB。在下一部分,b tmp = a.set();复制了b对象,因此没有 UB。 -
@GGinside 那是在谈论一个完全不同的问题,鉴于此代码
int a = 1; int& b = a; int c = 2; b = c;,有时初学者认为最后一个分配更改了b,因此它引用了c,但实际上它分配了@987654360 @ 到a和b仍然作为对a的引用。当人们说你不能重新绑定引用时,这意味着什么。