如果临时性是隐含的不可修改的,这是如何工作的

If temporaries are implicitly non-modifiable, how does this work?

本文关键字:何工作 工作 修改 临时性 如果      更新时间:2023-10-16

有人告诉我,在C++03中,临时变量是不可修改的。

然而,以下是在GCC 4.3.4上为我编译的(在C++03模式下):

cout << static_cast<stringstream&>(stringstream() << 3).str();

这是如何编译的?

(我不是在谈论与引用绑定的临时规则。)

有人告诉我,在C++03中,临时变量是不可修改的。

这是不对的。在其他情况下,临时值是通过评估右值创建的,既有非常量右值,也有常量右值。表达式的值类别和它所表示的对象的常量大多是正交的1。观察:

      std::string foo();
const std::string bar();

给定上述函数声明,表达式foo()是一个非常值,其求值将创建一个非常临时值,而bar()是一个创建非常临时值的非常值。

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

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

由于operator=是一个成员函数,您甚至可以为非常量值赋值:

std::string("hello") = "world";

这应该是足够的证据来说服您临时性是而不是隐式常量。

1:标量右值是一个例外,例如42。他们总是非常惊讶

首先,"修改临时"answers"通过右值修改对象"是有区别的。我会考虑后者,因为前者对讨论没有实际用处[1]。

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

对象的左值是必需的为了修改对象类类型的右值也可以用于在下修改其引用某些情况。[示例:a为对象调用的成员函数(9.3)可以修改对象。]

因此,右值本身不是const,但它们在除某些特定情况外的所有情况下都是不可修改的。

然而,在我看来,成员函数调用可以修改右值似乎表明,通过右值修改对象的绝大多数情况都得到了满足。

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

因此,答案是(稍微改变结论的问题措辞),通过成员函数访问的右值本质上是不可修改的。


[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{});
}

(感谢Luc Danton的代码!)