为什么非常量引用不能绑定到临时对象? [英] How come a non-const reference cannot bind to a temporary object?

查看:46
本文介绍了为什么非常量引用不能绑定到临时对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么不允许获取临时对象的非常量引用,getx() 返回哪个函数?显然,这是 C++ 标准禁止的但我对这种限制的目的很感兴趣,不是对标准的参考.

Why is it not allowed to get non-const reference to a temporary object, which function getx() returns? Clearly, this is prohibited by C++ Standard but I am interested in the purpose of such restriction, not a reference to the standard.

struct X
{
    X& ref() { return *this; }
};

X getx() { return X();}

void g(X & x) {}    

int f()
{
    const X& x = getx(); // OK
    X& x = getx(); // error
    X& x = getx().ref(); // OK
    g(getx()); //error
    g(getx().ref()); //OK
    return 0;
}

  1. 很明显,对象的生命周期不能成为原因,因为C++ 标准不禁止对对象的常量引用.
  2. 很明显,上面示例中的临时对象不是常量,因为允许调用非常量函数.例如,ref() 可以修改临时对象.
  3. 此外,ref() 允许您欺骗编译器并获得指向此临时对象的链接,从而解决了我们的问题.
  1. It is clear that the lifetime of the object cannot be the cause, because constant reference to an object is not prohibited by C++ Standard.
  2. It is clear that the temporary object is not constant in the sample above, because calls to non-constant functions are permitted. For instance, ref() could modify the temporary object.
  3. In addition, ref() allows you to fool the compiler and get a link to this temporary object and that solves our problem.

另外:

他们说将临时对象分配给 const 引用会延长此对象的生命周期"和尽管没有关于非常量引用的说法".我的附加问题.以下赋值是否会延长临时对象的生命周期?

They say "assigning a temporary object to the const reference extends the lifetime of this object" and " Nothing is said about non-const references though". My additional question. Does following assignment extend the lifetime of temporary object?

X& x = getx().ref(); // OK

推荐答案

从此 关于右值引用的 Visual C++ 博客文章:

... C++ 不想让你不小心修改临时文件,但直接调用非常量成员函数可修改的右值是显式的,所以允许...

... C++ doesn't want you to accidentally modify temporaries, but directly calling a non-const member function on a modifiable rvalue is explicit, so it's allowed ...

基本上,您不应该尝试修改临时对象,因为它们是临时对象并且现在随时都会消亡.允许您调用非常量方法的原因是,只要您知道自己在做什么并且明确说明(例如使用 reinterpret_cast),欢迎您做一些愚蠢"的事情.但是,如果您将临时引用绑定到非常量引用,您可以永远"继续传递它,只是为了让您对对象的操作消失,因为在此过程中您完全忘记了这是一个临时引用.

Basically, you shouldn't try to modify temporaries for the very reason that they are temporary objects and will die any moment now. The reason you are allowed to call non-const methods is that, well, you are welcome to do some "stupid" things as long as you know what you are doing and you are explicit about it (like, using reinterpret_cast). But if you bind a temporary to a non-const reference, you can keep passing it around "forever" just to have your manipulation of the object disappear, because somewhere along the way you completely forgot this was a temporary.

如果我是你,我会重新考虑我的功能设计.为什么 g() 接受引用,它会修改参数吗?如果不是,则将其设置为 const 引用,如果是,为什么要尝试将临时传递给它,难道您不关心它是您正在修改的临时值吗?为什么 getx() 无论如何都是临时返回的?如果您与我们分享您的真实场景以及您要实现的目标,您可能会得到一些关于如何实现的好建议.

If I were you, I would rethink the design of my functions. Why is g() accepting reference, does it modify the parameter? If no, make it const reference, if yes, why do you try to pass temporary to it, don't you care it's a temporary you are modifying? Why is getx() returning temporary anyway? If you share with us your real scenario and what you are trying to accomplish, you may get some good suggestions on how to do it.

违背语言并愚弄编译器很少能解决问题 - 通常会产生问题.

Going against the language and fooling the compiler rarely solves problems - usually it creates problems.


解决评论中的问题:1) <代码>X&x = getx().ref();//好吧,x 什么时候会死? - 我不知道也不在乎,因为这正是我所说的违背语言"的意思.该语言说临时文件在语句结束时死亡,除非它们绑定到常量引用,在这种情况下,它们会在引用超出范围时死亡".应用该规则,似乎 x 在下一条语句的开头已经死了,因为它没有绑定到 const 引用(编译器不知道 ref() 返回什么).然而这只是一个猜测.


Addressing questions in comment: 1) X& x = getx().ref(); // OK when will x die? - I don't know and I don't care, because this is exactly what I mean by "going against the language". The language says "temporaries die at the end of the statement, unless they are bound to const reference, in which case they die when the reference goes out of scope". Applying that rule, it seems x is already dead at the beginning of the next statement, since it's not bound to const reference (the compiler doesn't know what ref() returns). This is just a guess however.

2) 我清楚地说明了目的:不允许修改临时变量,因为它没有意义(忽略 C++0x 右值引用).问题那为什么我可以调用非常量成员?"是一个很好的答案,但我没有比上面已经提到的更好的答案.

2) I stated the purpose clearly: you are not allowed to modify temporaries, because it just does not make sense (ignoring C++0x rvalue references). The question "then why am I allowed to call non-const members?" is a good one, but I don't have better answer than the one I already stated above.

3) 好吧,如果我对 X& 中的 x 是正确的x = getx().ref(); 死在语句的最后,问题很明显.

3) Well, if I'm right about x in X& x = getx().ref(); dying at the end of the statement, the problems are obvious.

无论如何,根据您的问题和评论,我认为即使是这些额外的答案也不会让您满意.这是最后的尝试/总结:C++ 委员会认为修改临时变量没有意义,因此,他们不允许绑定到非常量引用.可能还涉及一些编译器实现或历史问题,我不知道.然后,出现了一些具体情况,并决定排除万难,他们仍然允许通过调用非常量方法直接修改.但这是一个例外 - 通常不允许您修改临时文件.是的,C++ 通常就是那么奇怪.

Anyway, based on your question and comments I don't think even these extra answers will satisfy you. Here is a final attempt/summary: The C++ committee decided it doesn't make sense to modify temporaries, therefore, they disallowed binding to non-const references. May be some compiler implementation or historic issues were also involved, I don't know. Then, some specific case emerged, and it was decided that against all odds, they will still allow direct modification through calling non-const method. But that's an exception - you are generally not allowed to modify temporaries. Yes, C++ is often that weird.

这篇关于为什么非常量引用不能绑定到临时对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆