关于如何识别右值或左值引用以及 if-it-has-a-name 规则

2024-03-24

我正在读托马斯·贝克尔的书article http://thbecker.net/articles/rvalue_references/section_05.html关于右值引用及其使用。在那里他定义了他所说的如果它有一个名字 rule:

声明为右值引用的东西可以是左值或 右值。区分的标准是:如果有名字,那么它就是 左值。否则,它是一个右值。

这对我来说听起来很合理。它还清楚地标识了右值引用的右值。

我的问题是:

  1. 你同意这个规则吗?如果没有,你能举一个可能违反这条规则的例子吗?
  2. 如果没有违反此规则。我们可以使用这条规则来定义表达式的右值/左值吗?

这是用于解释左值和右值之间差异的最常见的“经验法则”之一。

C++ 中的情况比这复杂得多,因此这只能是经验法则。我将尝试回顾几个概念,并尝试阐明为什么这个问题在 C++ 世界中如此复杂。首先让我们回顾一下从前发生的事情

一开始有C

首先,在一般编程语言的世界中,“左值”和“右值”最初意味着什么?

在 C 或 Pascal 等更简单的语言中,这些术语用来指代可以放置在L快速或在R赋值运算符的权限。

在像 Pascal 这样的语言中,赋值不是表达式而只是语句,差异非常明显,并且是用语法术语定义的。左值是变量的名称或数组的下标。

这是因为只有这两件事可以位于作业的左侧:

i := 42; (* ok *)
a[i] := 42; (* ok *)
42 := 42; (* no sense *)

在 C 中,同样的差异也适用,并且它仍然非常符合语法,因为您可以查看一行代码并判断表达式是否会生成左值或右值。

i = 42; // ok, a variable
*p = 42; // ok, a pointer dereference
a[i] = 42; // ok, a subscript (which is a pointer dereference anyway)
s->var = 42; // ok, a struct member access

那么 C++ 发生了什么变化呢?

小语言长大了

在 C++ 中,事情变得更加复杂,差异不再是语法上的,而是涉及类型检查过程,有两个原因:

  • 所有内容都可以保留在赋值的左侧,只要其类型具有合适的重载operator=
  • 参考

因此,这意味着在 C++ 中,您不能仅通过查看表达式的语法结构来判断表达式是否会生成左值。例如:

f() = g();

是一个在 C 中没有意义的语句,但在 C++ 中可能完全合法,例如,f()返回一个引用。表达方式就是这样v[i] = j为。。。工作std::vector: the operator[]返回对该元素的引用,以便您可以为其赋值。

那么区分左值和右值还有什么意义呢?当然,这种区别仍然与基本类型相关,但也决定了什么可以绑定到非常量引用.

那是因为你不想有这样的法律代码:

int &x = 42;
x = 0; // Have we changed the meaning of a natural number??

因此,该语言仔细指定什么是左值,什么不是,然后说只有左值可以绑定到非常量引用。所以上面的代码是不合法的,因为整数文字不是左值,所以非常量引用不能绑定到它。

注意const引用是不同的,因为它们可以绑定到文字和临时变量(本地引用甚至可以延长这些临时变量的生命周期):

int const&x = 42; // It's ok

到目前为止,我们只触及了 C++98 中已经发生的事情。这些规则已经比“如果它有名称,它就是左值”更复杂,因为您必须考虑引用。因此返回非常量引用的表达式仍被视为左值。

此外,这里提到的其他经验法则并不适用于所有情况。例如“如果你可以获取它的地址,那么它就是一个左值”。如果“获取地址”是指“申请operator&”,那么它可能会起作用,但不要欺骗自己认为您永远无法获得临时地址:this例如,临时成员函数内的指针将指向它。

C++11 发生了什么变化

C++11 通过添加 an 的概念,使 bin 更加复杂右值引用,即即使是非 const 也可以绑定到右值的引用。事实是它可以only应用于右值使其既安全又有用。我认为不需要解释为什么右值引用有用,所以继续吧。

这里的要点是,现在我们有更多的案例需要考虑。那么现在什么是右值呢?该标准实际上区分了不同类型的右值,以便能够在存在右值引用的情况下正确说明右值引用的行为以及重载解析和模板参数推导。所以我们有这样的术语xvalue, prvalue诸如此类的事情,让事情变得更加复杂。

我们的经验法则又如何呢?

因此,“所有有名称的东西都是左值”仍然可以是正确的,但可以肯定的是,每个左值都有名称是不正确的。返回非常量左值引用的函数是左值。按值返回某些内容的函数会创建一个临时值,并且它是一个右值,返回右值引用的函数也是如此。

那么“临时变量是右值”呢?这是真的,但也可以通过简单地转换类型将非临时值变成右值(就像std::move).

所以我认为,如果我们牢记它们是什么:经验法则,所有这些规则都是有用的。 它们总会有一些不适用的极端情况,因为要准确指定右值是什么和不是,我们无法避免使用标准中使用的确切术语和规则。这就是它们被写的原因!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于如何识别右值或左值引用以及 if-it-has-a-name 规则 的相关文章

  • 如何在联系我们页面中使用用户电子邮件发送电子邮件?

    我正在创建一个联系我们页面 并且我想从该页面接收邮件 因为它的邮件来自用户邮件 我写了这段代码 var client new SmtpClient smtp gmail com 587 Credentials new NetworkCred
  • 自定义可视化 Web 部件属性 sharepoint

    我在 Visual Studio 2012 中创建可视 Web 部件属性时遇到问题 我被提及http msdn microsoft com en us library ee231551 aspx http msdn microsoft co
  • 类型转换 sockaddr 结构

    我正在尝试学习网络编程 并在这个过程中学习C 我对结构感到困惑sockaddr这是一个通用地址 并且sockaddr in 我的书里是这么说的 因此 我们可以填写 sockaddr in 的字段 然后强制转换 a 指向 它指向 指向 soc
  • 将数据集导出到 EXCEL

    我使用以下代码将数据库表中的字段导出到 Excel 中 我想要做的是能够编写一条 SQL 语句从多个表中检索字段并将其导出到 Excel 中 这段代码只允许我导出一张表 另外 如何显示保存提示对话框 示例代码将不胜感激 非常感谢 prote
  • 实体框架 - 循环更新属性

    我正在尝试找到一种方法来循环 EF 对象的属性并更新这些属性的值 更具体地说 我有 50 个字段 其中最多填充 50 个下拉列表 所有 50 个可能都需要填充 也可能不需要填充 为了解决这个问题 我有一个中继器 最多可以创建 50 个 DD
  • 线程安全的get(访问器方法)

    我目前正在使用以下代码对变量进行线程安全访问 int gnVariable void getVariableValue int pnValue acquireLock Acquires the protection mechanism pn
  • WIX 自动生成 GUID *?

    假设我生成产品 ID 为 的 WIX XML 文件 另外 对于每个组件 GUID 我都使用
  • c++11 中的 std::thread 问题

    我在尝试从标准模板库编译具有多线程的程序时遇到一些麻烦 当我尝试编译以下程序时 它返回一个晦涩的错误 include
  • 从空白启动时 VSTO 功能区不显示解决方案

    如果我从 文件 新建项目 菜单创建一个新的 Excel 2013 和 2016 VSTO 加载项 项目 然后单击 项目 添加新项目 gt 功能区 可视化设计器 则一切正常 我启动了应用程序 我的功能区显示在 Excel 中 但是 如果我首先
  • 我应该使用函数还是无状态函子?

    这两段代码做同样的事情 如您所见 它将用于排序函数 哪个更好 我通常写后一种 但我看到一些程序员像以前那样做 struct val lessthan binary function
  • Boost async_write问题

    我将展示一些代码 void wh const boost system error code ec std size t bytes transferred std cout lt lt test int main int argc cha
  • 使用 cryptoapi CryptImportKey 导入公钥时出错

    我想将公钥 blob 导入到 CSP 但发生了错误 BYTE pbData 0xEB 0x2A 0x38 0x56 0x86 0x61 0x88 0x7F 0xA1 0x80 0xBD 0xDB 0x5C 0xAB 0xD5 0xF2 0x
  • 读取所有进程内存以查找字符串变量c#的地址

    我有 2 个用 C 编写的程序 第一个名为 ScanMe 的程序包含一个包含值 FINDMEEEEEEE 的字符串变量 以及一个值为 1546 22915487 的双精度变量 另一个名为 MemoryScan 的程序读取第一个程序的所有内存
  • 选择要重写哪个基类的方法

    鉴于以下情况 class Observer public virtual void Observe Parameter p 0 template
  • 如何从标准输入读取一行,阻塞直到找到换行符?

    我试图从命令行的标准输入一次读取任意长度的一行 我不确定是否能够包含 GNU readline 并且更喜欢使用库函数 我读过的文档表明getline应该可以工作 但在我的实验中它不会阻塞 我的示例程序 include
  • 什么是多重重继承?

    我将以下称为 多重重新继承 直接继承一个类一次 并通过继承其一个或多个后代来间接继承一次或多次 通过继承一个类的两个或多个后代来间接继承一个类两次或多次 我想知道它是否存在以及如何明确访问嵌入的子对象 1 Professional C 2n
  • 父窗体中的居中消息框[重复]

    这个问题在这里已经有答案了 有没有一种简单的方法可以在 net 2 0中将MessageBox居中于父窗体中 我在 C 中确实需要这个并发现中心消息框 C http bytes com topic c sharp answers 26712
  • 为了清楚起见,是否应该在返回类型上使用无用的类型限定符?

    当我们的头文件中有原型时 我们的静态分析工具会抱怨 返回类型上有无用的类型限定符 例如 const int foo 我们这样定义它是因为该函数返回一个永远不会改变的常量 认为 API 看起来更清晰const到位 为了清楚起见 我觉得这类似于
  • 当另一个进程使用 std::fstream 写入文件时从文件读取[重复]

    这个问题在这里已经有答案了 我需要从文件中逐行读取 它是由 std getline 完成的 另一个进程的问题是一直向其附加数据 然后我需要读取新行 例如 文件一开始包含10行 我的程序读取了10行 那么我的程序应该等待 过了一会儿 另一个进
  • 使用 wmi 获取活动会话(Win32_LogonSession 还返回非活动/旧会话)

    有没有办法只显示 wmi 的活动会话 问题是 Win32 LogonSession 还显示不活动 断开连接的会话 ManagementScope scope new ManagementScope ManagementPath Defaul

随机推荐

  • f77 未格式化二进制文件的内容

    我有一个 f77 未格式化的二进制文件 我知道该文件包含 2 个浮点数和一个长整数以及数据 文件的大小为 536870940 字节 应包含 512 3 个浮点数据值以及 2 个浮点和长整数 512 3 个浮点数据值组成 536870912
  • 将 HTML 文件导入到另一个 HTML 文件中

    我想知道如何将 HTML 文件导入到其他 HTML 文件中 这两个文件都引用许多不同的文件 因此我更愿意将它们保存在两个不同的文件夹中 而不是将一个文件复制到另一个文件中 目前 我正在使用 Django 进行本地开发 include fil
  • keycloak 上是否有用于更改用户密码的 API 调用?

    我正在尝试实现自己的表单来更改用户的密码 我试图在 Keycloak 中找到用于更改用户密码的 API 但在文档中找不到任何内容 有API可以做到这一点吗 您可以使用PUT auth admin realms realm users id
  • 调用渲染与绘制 DOM?

    我正在学习 React 并试图更好地理解生命周期和不同阶段 我刚刚读到的一件事是 React 首先渲染然后安装元素 在这种情况下渲染意味着调用类的 render 而不是绘制 DOM 我想我只是不太明白这意味着什么 有人可以用简单的方式或举例
  • Ansichar 和 char 有什么区别? [复制]

    这个问题在这里已经有答案了 我最近遇到了这种数据类型不匹配的情况 这是我以前从未见过的 我希望有人能解释它们是什么以及它们有何不同 我得到的错误是 F2063 DCC 错误 E2010 不兼容的类型 AnsiChar 和 Char 历史上在
  • 增加 ulimit Mac OS X 10.8

    I m learning MongoDB and when I start the mongo shell a wild warning message appeared It says 我如何更改 软限制 我使用的是 Mac OSX 10
  • 如何删除 Hudson 的构建工件?

    我们使用 Hudson 作为我们的持续集成服务器 它非常棒 我们有两个问题 它们有轻微的相关性 https hudson dev java net issues show bug cgi id 2736 https hudson dev j
  • 将数据集加载到数据库时,DBUnit 出现 NoPrimaryKeyException

    当我尝试运行使用 DBUnit 的单元测试之一时 我收到 NoPrimaryKeyException 数据表是使用 Hibernate 创建的 是映射多对多关系的两个类之间的连接表 定义关系的注解如下 Override ManyToMany
  • Pagedown markdown 脚本插入图像 url 一次

    我有一个修改后的 pagedown markdown 标记脚本 用于将图像 url 插入编辑器 但它仅在第一次起作用 我已经用注释解释了我的代码
  • 使用 python scapy 发送 DHCP Discover

    我是Python新手 正在学习一些网络编程 我希望通过我的tap接口向我的DHCP服务器发送一个DHCP数据包 并期待它的一些响应 我尝试了几种数据包构建技术 例如 structs 和 ctypes 最终使用 scapy 在这里 我能够发送
  • 附加属性有哪些不同的用途?

    到目前为止 我在 WPF 的冒险经历中已经看到了 AttachedProperties 的一些非常不同的用途 我想知道其中有哪些不同的用途 我见过相当普通的用途 例如 Grid 和 Canvas 中的用途 以及一些非常酷的技巧 允许在没有
  • 在 Jupyter Notebook 中重新加载 Python 模块(不自动重新加载)

    我有以下文件夹结构 project src init py mymodule py mynotebook ipynb within mynotebook我可以导入mymodule使用标准公式from src mymodule import
  • 如何使用空格或缩进注释多行

    在 Visual Studio 2010 中 我有多行文本需要注释 A B C Using CTRL E C to comment out multiple lines I get A B C 我想在之间有一个空格 或缩进 and A he
  • GNUPLOT:点图,数据取决于点大小

    我正在尝试绘制由 3 个坐标组成的数据集 X 坐标 x 坐标和出现次数 例子 1 2 10 3 1 2 3 2 1 我想在 x y 处为每条线画一个点 其直径取决于第三个值 Gnuplot 可以做到这一点吗 创建具有可变点大小的二维图 看t
  • CSS非标准“ZOOM”属性

    我有一个 css 文件 其中包含一个带有 Zoom 1 的类 我在浏览器控制台上收到以下错误 该页面使用非标准的 缩放 属性 相反 您可以使用 calc 或将 transform 与 transform origin 0 0 一起使用 如何
  • $redis 全局变量与 ruby​​ on Rails

    我使用 redis 作为读取缓存 我创建了一个初始化程序 配置 初始化程序 redis rb redis Redis new host gt ENV REDIS HOST port gt ENV REDIS PORT 每当创建新工作人员时
  • 未在命名空间中捕获 PDOException

    我不知道怎样才能抓住PDOException在下面的代码中 请告诉我下面的代码中哪里抛出异常 我有 目录 folder 1 b php 2 c php autoloader in the b php and in c php class c
  • 测试“0”、“-0”、“0.0”、“00”时的 PHP 和 Perl 行为

    当 PHP Perl 测试一个值时 我遇到了这个有趣的行为 print 0 Yes No gt No print 00 Yes No gt Yes print 0 0 Yes No gt Yes print 0 Yes No gt Yes
  • 为什么C#中没有反向枚举器?

    有谁知道是否有特定原因或设计决定不在 C 中包含反向枚举器 如果有一个与 C 相当的东西就好了reverse iterator就像 Enumerator 相当于 C 一样iterator 可以反向迭代的集合只需实现 IReverseEnum
  • 关于如何识别右值或左值引用以及 if-it-has-a-name 规则

    我正在读托马斯 贝克尔的书article http thbecker net articles rvalue references section 05 html关于右值引用及其使用 在那里他定义了他所说的如果它有一个名字 rule 声明为