函数引用的参数在 c++ 中必须为 const 的直观原因 [duplicate]

An intuitive reason why function's referenced parameter must be const in c++ [duplicate]

提问人:forstack overflowizi 提问时间:2/21/2021 更新时间:2/21/2021 访问量:33

问:

我正在看这个代码:

A foo() {
    cout << "foo" << endl;
    A a;
    return a;
}
void bar(const A& a) {
    cout << "bar" << endl;
}
int main() {
        A a;
        bar(a);
        bar(foo());
}

并试图理解为什么 C++ 语言如此急于让我在传递临时对象时将 infront 放在前面,就像我在 .
毕竟,如果可以访问临时对象,那么为什么对我来说也要更改它呢?
有时我会传递一个 lValue 并根据需要更改它,有时我会发送一个 rValue 并会浪费一点资源来更改它,然后,临时对象将被删除。最大的问题是什么?一些浪费的时钟周期?我可以忍受!右?
为什么有人要关心我如何处理我的临时对象?他们很快就会被删除,他们的信仰被认为不关任何人的事。
constA& abarbar(foo());bar()bar()

C++ 引用 常量 传递引用 临时对象

评论


答:

0赞 forstack overflowizi 2/21/2021 #1

答案是 !
太容易忘记或混淆我何时传递 lValue 和何时传递 rValue。
持有对真实对象的引用并更改它(写入它)是所需的功能!
乍一看,持有对临时对象的引用并对其进行更改是无害的!右?写入临时对象可能发生的最坏情况是什么?反正很快就会消失的。.
这当然不是真的。
如果 c++ 允许我传递一个非常量临时对象,那么我有责任始终确保在需要传递 lValue 时,我永远不会错误地将临时对象传递给!
这是难以检测的错误的来源。所以最好把程序员从自己身上拯救出来,不要让他写给临时对象的能力,不是因为我们想保存临时对象,而是因为我们想在COMPILE TIME的早期拯救程序员关于他传递rValue的逻辑错误,而他实际上想改变一个lValue。
例如,请考虑以下代码:
foo()main()bar()bar()

A foo() {
    cout << "foo" << endl;
    A a;
    return a;
}
A& dim(A& a) {
    return a;
}
void bar( A& a) {
    cout << "bar" << endl;
}
int main() {
    A a;
    bar(dim(a));
}

这里我们不需要使用 const,因为现在从 .
人类如何跟踪何时传递对 lValue 的引用,以及何时传递对 rValue 的引用?他不能。 如果 c++ 允许某个方法接受对 rValue 的引用,那么它将成为一个真正的硬错误,并且不会使开发人员受益。曾。
我相信,如果你现在正在阅读这篇文章,希望你会像我一样 - 我不希望 c++ 允许我写一个临时对象!没用!它可能会使我的生活复杂化,迫使我检查自己某个方法是否返回对 lValue 或 rValue 的引用。
这就是为什么在这里很重要的原因,它在同一函数的两个版本之间创建了区别:一个可以更改对象,一个不能更改对象
bar()dim()const

请看这段代码:

class A {
public:
    A() { cout << "A ctor" << endl; }
    A(const A& o){ cout << "A cctor" << endl; }
    ~A() { cout << "A Dtor" << endl; }
};
A foo() {
    cout << "foo" << endl;
    A a;
    return a;
}
A& dim(A& a) {
    return a;
}
void bar( A& a) {
    cout << "bar" << endl;
}
void bar(const A& a) {
    cout << "const bar" << endl;
}
int main() {
    A a;
    bar(dim(a));
    bar(foo());
}

在这里,我们有两个几乎相同的方法,它们都命名了,并且都接收到 A 实例的引用。
唯一的区别是其中一个可以更改引用,而另一个不能。
调用将调用
Where 将最后一次调用
So:如果 c++ 允许我将 rValue 发送到可以更改该 rValue 的方法,并且如果我犯了使用此选项的错误 - 这肯定是一个逻辑错误!因为没有理由更改 rValue。
逻辑错误比编译错误更难调试。
barbar(dim(a))void bar( A& a)bar(foo())bar(const A& a)