微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c++中函数的引用参数必须是const的一个直观原因

如何解决c++中函数的引用参数必须是const的一个直观原因

我正在查看此代码

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());
}

并试图理解为什么当我传递 const 一个临时对象时,C++ 语言如此着急让我将 A& a 放在 bar 前面,就像我在 {{ 中所做的那样1}}.
毕竟,如果可以访问临时对象,那为什么我还要更改它呢?
有时我会传递一个 lValue 并且 bar(foo()); 会根据需要更改它,有时我会发送一个 rValue 而 bar() 会浪费一点资源来更改它,然后,临时对象将被删除。有什么大问题?一些浪费的时钟周期?我可以忍受这一点!对吗?
为什么有人应该关心我如何处理我的临时对象?他们很快就会被删除,他们的信仰不关任何人的事..

解决方法

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

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,因为 bar() 现在从 dim() 获取对 lValue 的引用。
人类如何跟踪他何时传递对 lValue 的引用,以及何时传递对 rValue 的引用?他不能。 如果 c++ 允许一个方法接受对 rValue 的引用,那么调试将成为一个真正的硬错误,并且不会使开发人员的任何使用受益。永远。
我相信到目前为止,如果您正在阅读本文,您希望能像我一样-我不希望 C++ 允许我写入临时对象!没用的!它会使我的生活复杂化,迫使我检查自己是否某个方法返回对 lValue 或 rValue 的引用。
这就是 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());
}

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。