c++:允许临时对象调用非常量成员函数的设计理念是什么?

c++: what's the design philosophy of allowing temporary object to call non-const member function?

我搜索堆栈溢出,人们说修改临时对象是愚蠢的,所以不允许将临时对象绑定到非常量左值引用,就像你不能将临时对象传递给具有非常量的函数一样左值参考。

那为什么允许临时对象调用非常量成员函数,它有可能修改对象并做 "stupid" 事情?你可能会说,“哈,这是允许的,因为我们想为程序员提供一些灵活性来做 "stupid" 实际上并不那么愚蠢的事情”,这就是我很难购买的原因,因为如果我购买这个借口, 我认为 "binding temporary to non-const lvalue reference" 可以用同样的理由来证明。

谢谢!我在这里几乎找不到任何相关问题。他们只是告诉我这是一个例外,但为什么我们允许这个例外?

假设您有一个工厂方法,returns,按照建议,unique_ptr

std::unique_ptr<MyClass> createObject();

但是您需要一个指向已创建对象的共享指针。所以你写

std::shared_ptr<MyClass> mySharedObject{createObject().release()};

并且您刚刚对一个临时对象调用了一个非常量方法。我觉得很有用。

好的。我忘了 shared_ptr 构造函数接受 unique_ptr。但是,为什么禁止例如快速读取文件的第一行?

std::array<char, 140> line;
std::istream{"MyFile.txt"}.readline(line, line.size()-1);

也许更有趣的是为什么禁止将非常量左值引用绑定到临时值?对左值参数的非常量引用意味着输出参数。允许绑定到 temporary 会导致由于转换而导致的细微错误。例如

void readShort(short & out)
{
   out = 7;
}

long var;
readShort(var);

已创建临时 short 以匹配函数参数类型。现在禁止将其绑定到引用。如果允许,函数将分配给临时值,然后结果将被丢弃。

更新

Could you also explain why binding temporary object to local non-const lvalue reference is not allowed?

现在有一套绑定对象引用的规则,无论是在函数调用期间还是在本地引用定义期间完成。根据上下文创建两组不同的规则会使语言复杂化(已经非常复杂)并且需要一些理由。我猜还没有人提出能够说服标准委员会的更改请求。

您不能将临时变量绑定到非常量引用,但这里的基本原理是而非以避免意外修改临时变量。理由是你不想默默地错过修改你想要修改的东西。

假设它是允许的,那么:

void foo(double& x);
int y;
foo(y); //user wants to modify y, but instead a temporary is modified

就其本身而言,修改临时对象完全没问题,而且通常很有用。没有理由禁止它。

只是一些补充:不允许将临时绑定到本地非常量左值引用的原因。

首先,请阅读我接受的答案。

那么,如果允许临时绑定到本地非常量左值引用,你可以这样写代码:

void foo(double& x);
int& ref = 1;
foo(ref);

这与我接受的答案提供的原因相同。

好的,我在这里添加一些额外的材料。以下资料引用自David Vandevoorde, Nicolai M. Josuttis, Douglas Gregor-C++ Templates_ The Complete Guide-Addison-Wesley (2017), C.2.1 The Implied成员函数的参数。

“An old special-case permits an rvalue to be bound to an lvalue reference to non-const type when that reference is the traditional implicit *this parameter”

struct S{
    void f1() {}//the old rule
    void f2() && {}
    void f3() & {}
};
int main()
{
    S().f1();//Here, I THINK const this is bound to non-const, thus allowing calling non-const member functions.(the comment here is not quoted from the book.)
    S().f2();
    S().f3();//not okay
    return 1;
}

使用-std=c++11编译选项。 所以,这意味着 C++ 设计者已经意识到允许具有隐式 const this* 的临时对象调用非常量成员函数的旧规则并不是很好。所以在C++11中他们引入了&&&后缀函数声明。

但谈到允许临时对象调用非常量成员函数的旧规则的设计理念,我认为不值得深究。 C++ 11 已经努力 "emend" 这个。(或者让程序员控制这个。)