为什么允许通过 const 引用传递右值,而不允许通过普通引用传递右值?

问题描述 投票:0回答:5

以下程序

void display(const int& a)
{
    cout << a ;
}

如果用这样的文字调用就会起作用

display(5);

但是如果没有

const
,它就无法工作。

那么

const
引用如何保持指向右值(临时对象)?

c++ parameters literals rvalue pass-by-const-reference
5个回答
46
投票

最后一个问题:

const 引用如何保持指向 R 值(匿名变量)

这就是答案。 C++ 语言表示,局部 const 引用会延长临时值的生命周期,直到包含范围结束,但会节省复制构造的成本(即,如果您要使用局部变量)。


25
投票

将任何对象视为内部包含某些值的 box,并且该框可能有也可能没有名称标签,即 with 名称标签的框为

variable
,而 without 名称标签的框为
literal
。不管有没有名牌,我们有盒子。


Reference
是我们将名称标签添加到盒子中的方式。

int a = 5;
int &b = a;

我们的盒子有两个名称标签(里面有值

5
)。

const int &c = 5;

你在这里,这个盒子刚刚被命名。


以前从未有过名称的盒子的新名称必须标记为

const
。因为盒子里面的值可以通过它的名字来改变,我们不希望这种情况发生(不允许发生)到我们的
literal
盒子。


5
投票

回到文字的定义。文字是一个常量;例如尽管变量可能会从分配的值 5 更改为另一个值,但数字 5 的值永远不会改变。通过引用传递文字意味着该函数可以修改它,根据定义,这是您不能对文字执行的操作,这就是语言要求您使用 const 修改它的原因。我不认为 C++ 可以修改文字,即使它让你尝试,但它仍然强制执行此约定以提醒程序员文字值无法修改。


3
投票

因为文字是不变的。 1 不能变成 2,

"abd"
不能变成
"edf"

如果 C++ 允许您通过非

const
引用获取文字,那么它会:

  1. 必须允许文字动态改变它们的含义,允许你让 1 变成 2。
  2. 希望程序员格外小心,仅通过那些不引用文字的引用来修改值,如果出错,则会调用未定义的行为。

(1) 会在你的程序中造成混乱,因为

x == 1
可能意味着“x 等于 2”,具体取决于上下文,而 (2) 是不可能实现的,因为
void display(int& a)
应该如何知道它是否收到一个字面参考还是非字面参考?

由于这两个选项都没有意义,因此文字只能通过

const
引用传递。


实际上,从字符串文字到

char*
的已弃用转换是一个很好的例子,说明了为什么这些规则很有意义,尽管它不是引用而是指针。您可以让
char*
指向
"abc"
,但尝试实际利用
char*
的“可修改性”属性并修改
char
元素之一会导致未定义的行为。这使得整个已弃用的转换既危险又无用(在非遗留代码中)。

您不想在语言的所有其他部分遇到这样的麻烦,不是吗?


1
投票

右值是一个临时的消失对象,可以读取但即将被销毁。它也是一个不能保留在赋值左侧的值(你怎么能理解给这样一个幽灵赋值呢?)

C++ 有一种非常具体的方法来处理此类实体。如果您可以通过(非常量)引用传递右值,您也可以从函数内部分配给它。因此,如果要通过引用传递 r 值,则该规则必须是 const 引用。

但这并不是全部事实,因为你确实有 r 值引用(用

&&
表示)。因此,您最终可以操作临时对象,但您必须使用右值引用明确声明您确实想要这样做。

© www.soinside.com 2019 - 2024. All rights reserved.