如何得到非const引用不能绑定到临时对象?

如何得到非const引用不能绑定到临时对象?

问题描述:

为什么不允许非临时对象引用
函数 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引用扩展了这个对象的生命周期和没有关于非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 ++不希望你不小心
修改临时值,而是直接
调用非成员函数
a可修改右值是显式的,所以
是允许的...

... 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 ...

基本上,你不应该尝试修改临时性,因为它们是临时对象,而且会立刻死亡。允许调用非const方法的原因是,只要你知道你在做什么,你是明确的(比如,使用reinterpret_cast),欢迎你做一些愚蠢的事情。但是如果你绑定一个临时的非const引用,你可以继续传递它永远只是为了你的对象的操作消失,因为在某个地方,你完全忘了这是一个暂时的。

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(); // OK when will x die? - 我不知道,我不在乎,因为这正是我的意思是违背语言。语言说临时在语句的末尾死去,除非它们被绑定到const引用,在这种情况下,当引用超出范围时,它们死亡。应用该规则,似乎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 = 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 ++委员会决定修改临时表没有意义,因此,它们不允许绑定到非const引用。可能是一些编译器实现或历史问题也涉及,我不知道。然后,一些特定的情况出现,并且决定,对于所有的可能性,他们仍然允许通过调用非const方法的直接修改。但这是一个例外 - 你通常不允许修改临时。是的,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.