- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这个非常简单的代码是允许的:
class s
{
public:
};
const s& tt = std::move(s()); // Also valid without 'const'
但现在我想知道为什么它被允许..
首先我们使用 std::move
并将右值(临时)标记为右值引用,但为什么左值引用可以绑定(bind)到右值引用?
是因为右值引用也是右值吗?
导致左值引用绑定(bind)到右值引用的基本原理(或标准引号)是什么?可以做到我明白了。
编辑:msvc2015 允许非 const 左值引用绑定(bind)到右值引用,问题仍然是 const 左值引用绑定(bind)到右值引用。抱歉,我应该指定我使用的编译器。
最佳答案
作为标准转换之一(C++ 标准第 4 章),右值引用被隐式转换为右值(更具体地说,转换为 xvalue):
The effect of any implicit conversion is the same as performing the corresponding declaration and initialization and then using the temporary variable as the result of the conversion. The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type (8.3.2), an xvalue if T is an rvalue reference to object type, and a prvalue otherwise
右值(包括 xvalue)可以绑定(bind)到 const
左值引用,这样您就可以将临时值传递给具有此类参数的函数:
void foo(const bar &a);
// ...
foo(bar());
(临时值是右值;在本例中,bar()
的结果是右值)。没有理由不允许允许这样做,因为临时对象总是与包含表达式(在本例中为函数调用)一样长,因此它不会在 foo 中创建悬空引用
。
这意味着总是可以将函数 fun(bar)
的签名调整为 fun(const bar &)
- 当然也可以相应地更改实现! - 因为临时参数仍然会被接受,并且从调用者的角度来看语义应该是相同的; const
表示该对象不会被修改,如果通过复制传递也是如此。
不允许使用非const
引用;一个实际的原因是因为它们暗示应该以某种有意义的方式修改该值,如果该值是临时的,它将丢失。但是,如果您真的想这样做,可以将右值转换为左值,但有一些注意事项,如 this answer 中所述。另一个问题。
允许右值绑定(bind)到 const
左值引用,除了允许通过引用传递临时参数外,对于不知道确切参数类型但又希望允许的情况也有好处如果可能的话移动语义。假设我正在调用一个可以定义为 foo2(const bar &)
或 foo2(bar)
的函数,在前一种情况下,它可能有也可能没有重载foo2(bar &&)
,并且我希望尽可能使用移动语义(假设 foo2(bar &&)
重载将在其实现中使用移动语义) ;我可以安全地使用 std::move
来创建右值,因为它适用于任何一种情况。这个例子可能看起来有点做作,但这是编写模板时经常会出现的事情。在代码中:
bar bb = bar();
foo2(std::move(bb));
// above is legal if foo2 is declared as either:
// foo2(bar)
// foo2(const bar &)
// and in latter case calls overload foo2(bar &&) if it is defined.
在涉及临时对象的其他右值到左值引用赋值的情况下,临时对象的生命周期会延长到引用的生命周期,因此即使在参数传递以外的上下文中也不会创建悬挂引用:
const bar &b = bar(); // temporary lifetime is extended
在上面,bar
对象不会被销毁,直到引用 b
超出范围。
关于c++ - 为什么 const/nonconst 左值引用都绑定(bind)到右值引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40909095/
我想知道最终用户按下了什么,所以我使用了 getch() 。 如果用户按右,我可以获得0xE0 0x4D。 如果用户按下Ctrl+右,我可以获得0xE0 0x47。 如果用户按下Shift+右,我可以
我已经构建了一个应用程序来搜索我的位置。 这是代码 var map; var gdir; var geocoder = null; var addressMarker; function init
我想为我的元素设计布局 View 。布局 View 在左 Angular 和右 Angular (同一行)有一个图像,将有 2 行单词,一行在第 1 行,另一行在第 2 行。我该如何实现? It
我有一个很长的线性(分支不多)流程图,在 graphviz 中显示为要么太高而无法放在单个页面上,要么太宽(如果方向是从左到右) 是否有一种简单的方法可以让 graphviz 以从左到右,然后向下,然
我一直摸不着头脑,但运气不好。设计器有一个包含 3 栏的站点、两个侧边栏和一个主要内容区域。 专为桌面设计,左栏、主要内容、右栏。但是,在较小的设备上,我们希望首先堆叠主要内容。 所以通常情况下,你可
我想要从上到下和从左到右组织的 css block 。 为了更好地解释这是一张图片,其中包含我到目前为止所获得的内容以及我希望使用 CSS 实现的内容: 代码如下: HTML: 1 2 3 4 5
当我问this question时,答案之一(现已删除)建议Either类型对应Curry-Howard correspondence中的XOR而不是OR,因为它不能同时是Left和Right。 真相
如果一行中六个观察值中至少有三个是 != NA,我想计算该行的平均值。如果存在四个或更多 NA,则平均值应显示为 NA。 给出平均值的例子,忽略了 NA: require(dplyr) a % mut
我有一个由 9 列组成的数据框,其中包含一个因素 list 。每行可以填充所有 9 列(因为在该行中包含 9 个“事物”),但大多数没有(大多数有 3-4 个)。列也不是特定的,就像第 1 列和第 3
这是我第一次尝试使用 R 构建函数。基本上我的预期目标如下。 使用 RoogleVision 包与 Google Cloud Vision API 通信 函数遍历目录中的图片 从每张图片的 Googl
使用: mean (x, trim=0.05) 从分布的每一侧移除 2.5%,这对于对称的双尾数据来说很好。但是如果我有一个尾部或高度不对称的数据,我希望能够只删除分布的一侧。有没有这个功能,还是我自
我想保留重复的列,并删除唯一的列。这些列将具有相同的值,但名称不同。 x1 = rnorm(1:10) x2 = rnorm(1:10) x3 = x1 x4 = rnorm(1:10) x5 = x
是否可以使WPF工具栏中的元素的Right水平对齐方式正确? 我尝试将内部元素添加到Grid中,并将ColumnDefinition分配给Left / Right。我
datatable(head(iris)) 如何将我的列居中,使其位于我的列名称的正下方? 最佳答案 您可以使用options 下的columnDefs 自变量。将 className 设置为 dt-
我是 R 的新手,但我正在尝试在 R 中制作滑动窗口。 使用循环我可以像这样,但这变得非常低效。 results=c(1:7) letters=c("A","B","C","D","E","F","G
假设我有这个 .txt 文件: here is line 1 here is line 2 here is line 3 here is line 4 我想将此字符串粘贴到第 3 行和第 4 行之间:
假设我有这个 .txt 文件: here is line 1 here is line 2 here is line 3 here is line 4 我想将此字符串粘贴到第 3 行和第 4 行之间:
我想知道我的环境中有什么类型的对象。 我可以像这样显示谁在那里: ls() 但是运行类似的东西 sapply(ls(), class) (显然)不会告诉我们我们拥有什么类型(类)的对象(函数、数字、因
我想创建一个带有水平标签的树状图,但让叶子根据它们的高度悬挂,而不是仅仅下降到图的边缘。 例子: par(mfrow = c(1,2)) hc <- hclust(dist(USArrests), "
我的 CSS 中有一个元素,如下所示 .xyz{ position:absolute; left:50%; } 现在正如预期的那样,当我减小浏览器窗口的宽度时,这个元素向左移动
我是一名优秀的程序员,十分优秀!