如果临时性是隐含的不可修改的,那么它是如何工作的呢?

Lig*_*ica 11 c++ temporaries

我被告知,在C++ 03中,临时性是隐含的不可修改的.

但是,以下为GCC 4.3.4编译(在C++ 03模式下):

cout << static_cast<stringstream&>(stringstream() << 3).str();
Run Code Online (Sandbox Code Playgroud)

这是怎么编译的?

(我不是在谈论有关临时引用的临时规则.)

fre*_*low 20

我被告知,在C++ 03中,临时性是隐含的不可修改的.

这是不正确的.在其他情况下,通过评估rvalues来创建临时值,并且存在非const rvalues和const rvalues.表达式的值类别和它表示的对象的常量大多是正交1.注意:

      std::string foo();
const std::string bar();
Run Code Online (Sandbox Code Playgroud)

给定上面的函数声明,表达式foo()是一个非const rvalue,其求值创建一个非const临时值,并且bar()是一个const rvalue,它创建一个const临时值.

请注意,您可以在非const rvalue上调用任何成员函数,允许您修改对象:

foo().append(" was created by foo")   // okay, modifying a non-const temporary
bar().append(" was created by bar")   // error, modifying a const temporary
Run Code Online (Sandbox Code Playgroud)

由于operator=是成员函数,您甚至可以分配给非const rvalues:

std::string("hello") = "world";
Run Code Online (Sandbox Code Playgroud)

这应该足以说服你,临时不是隐含的常量.

1:异常是标量右值,例如42. 它们总是非常量的.


Lig*_*ica 8

首先,"修改临时"和"通过右值修改对象"之间存在差异.我会考虑后者,因为前者对讨论并不是很有用[1].

我在3.10/10(3.10/5在C++ 11中)发现了以下内容:

为了修改对象,对象的左值是必要的,除了在某些情况下也可以使用类类型的右值来修改它的指示对象.[示例:调用对象(9.3)的成员函数可以修改对象.]

因此,rvalues不是const本身,但除了某些特定情况外,它们都是不可修改的.

但是,成员函数调用可以修改rvalue似乎向我表明,通过rvalue修改对象的绝大多数情况都得到满足.

特别是,(obj1+obj2).show()对于非const show() [ugh,为什么?!]无效的断言(在我链接到的原始问题中)是错误的.

所以,答案是(稍微改变问题的措辞结论)是右值,通过成员函数访问,是不是固有的不可修改的.


[1] - 值得注意的是,如果您可以从原始右值获得临时值的左值,您可以随意做任何事情:

#include <cstring>

struct standard_layout {
    standard_layout();
    int i;
};

standard_layout* global;

standard_layout::standard_layout()
{
    global = this;
}

void modifying_an_object_through_lvalue(standard_layout&&)
{
    // Modifying through an *lvalue* here!
    std::memset(global, 0, sizeof(standard_layout));
}

int main()
{
    // we pass a temporary, but we only modify it through
    // an lvalue, which is fine
    modifying_an_object_through_lvalue(standard_layout{});
}
Run Code Online (Sandbox Code Playgroud)

(感谢Luc Danton的代码!)