了解左值/右值表达式与对象类型

2024-02-01

我读过一些之前的最佳答案以及 Stroustrup 的“C++ 编程语言”和“Effective Modern C++”,但我很难真正理解表达式的左值/右值方面与其类型之间的区别。在《Effective Modern C++》的简介中说:

确定表达式是否为左值的一个有用的启发式方法是询问是否可以获取其地址。如果可以的话,通常是这样。如果不能,它通常是一个右值。这种启发式的一个很好的功能是,它可以帮助您记住表达式的类型与表达式是左值还是右值无关......在处理右值引用类型的参数时记住这一点尤其重要,因为参数本身是一个左值。

我不明白一些事情,因为我不明白为什么如果你有一个右值引用类型参数,你需要通过以下方式将其实际转换为右值:std::move()使其有资格被移动。即使参数(所有参数)是左值,编译器也知道其类型是右值引用,那么为什么需要告诉编译器它可以移动呢?这似乎是多余的,但我想我不明白两者之间的区别type表达式及其左值/右值性质(不确定正确的术语)。

Edit:

为了跟进下面的一些答案/评论,仍然不清楚的是为什么doSomething()下面我需要将参数包装在std::move()让它绑定到右值引用并解析为第二个版本doSomethingElse()。我知道,如果这种情况隐式发生,那就很糟糕了,因为参数将被移走,并且在此之后人们可能会无意中使用它。参数的右值引用类型性质似乎在函数中毫无意义,因为它的唯一目的是在给定右值作为参数传入的情况下绑定解析到函数的正确版本。

Widget getWidget();
void doSomethingElse(Widget& rhs);  // #1
void doSomethingElse(Widget&& rhs); // #2

void doSomething(Widget&& rhs) {
  // will call #1
  doSomethingElse(rhs);
  // will call #2
  doSomethingElse(std::move(rhs));      
}

int main() {
  doSomething(getWidget());
}

我不明白为什么如果你有一个右值引用类型参数,你需要通过以下方式将其实际转换为右值std::move()使其有资格被移动。

正如引文所说,types https://en.cppreference.com/w/cpp/language/type and 价值类别 https://en.cppreference.com/w/cpp/language/value_category是不同的东西。参数始终是左值,即使其类型是右值引用;我们必须使用std::move将其绑定到右值引用。假设我们允许编译器隐式执行此操作,如以下代码片段所示,

void foo(std::string&& s);
void bar(std::string&& s) {

    foo(s);  

    // continue to use s...
    // oops, s might have been moved

    foo(std::string{}); // this is fine;
                        // the temporary will be destroyed after the full expression and won't be used later

}

所以我们必须使用std::move明确地告诉编译器我们知道我们要做什么。

void bar(std::string&& s) {

    foo(std::move(s));  

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

了解左值/右值表达式与对象类型 的相关文章

  • X11 模式对话框

    如何使用 Xlib 在 X11 中创建模式对话框 模态对话框是一个位于应用程序其他窗口之上的窗口 就像瞬态窗口一样 并且拒绝将焦点给予应用程序的其他窗口 在 Windows 中 当试图从模态窗口夺取焦点时 模态也会通过闪 烁模态窗口的标题栏
  • Linq - 从表达式 创建表达式

    我有一个谓词Expression
  • 是否有可能劫持标准输出

    我正在尝试使用 C 重定向 Windows XP 上已运行进程的标准输出 我知道如果我自己生成进程 我可以做到这一点 但对于这个应用程序 我更喜欢一个 监听器 我可以附加到另一个进程 这在纯 Net 中可能吗 如果不可能 在 Win32 中
  • 为什么我会收到未找到分析器的警告?

    我创建了一个玩具项目来检查最新的 NET 7 预览版 5 和正则表达式代码生成 它效果很好 所以我对现有项目应用了相同的更改 不是为了生产 而是为了个人生产力 由于某种原因 我收到这些警告 CS8032 An instance of ana
  • NDK 应用 onDestroy 清理 - 如何 DetachCurrentThread

    因此 如果我们连接 我们必须在完成后分离线程 对吗 JNIEnv get jni env JNIEnv res JAVA VM gt GetEnv void res JNI VERSION 1 6 Using cached JavaVM J
  • 将公历日期转换为儒略日期,然后再转换回来(随着时间)

    我正在编写一个程序 必须将当前的公历日期和时间转换为儒略日期 然后再转换回公历门 最终我需要添加能够添加年 月 日 小时 分钟和秒的功能 但我需要先解决这部分问题 现在我已经从公历日期转换为儒略日期 所以从逻辑上讲 我觉得我应该能够以某种方
  • 如何自定义 Google 测试失败消息?

    我编写了一个如下所示的 Google 测试 它将一些计算值与 CSV 文件中预期存储的值进行比较 class SampleTest public testing Test public void setupFile const std st
  • 调用异步方法在视图模型的构造函数中加载数据有警告

    我的视图包含一个 ListView 它显示来自互联网的一些数据 我创建一个异步方法来加载数据并在我的视图模型的构造函数中调用该方法 它有一个警告提示我现在使用await关键字 还有其他解决方案可以在构造函数中异步加载数据吗 有几种可以应用的
  • 处理“未找到细胞”。 Excel 中的错误

    我正在使用 Excel VSTO 应用程序并使用以下代码在工作表中查找错误单元格 Excel Range rngTemp Excel Range rngErrorRange Excel Worksheet Sheet1 Excel Work
  • 我可以将 UseCSharpNullComparisonBehavior 用于单个查询吗?

    我有一个查询 该查询曾经是存储过程 现已转换为 EF 查询 现在已经超时了 使用 SQL Profiler 我可以看到生成的 SQL 的唯一区别是 EF 转变的新行为entity Property value into entity Pro
  • 如何构建一棵与或树?

    我需要一个支持 与 和 或 的树结构 例如 给定一个正则表达式 如ab c d e 我想把它变成一棵树 所以 一开始我们有两个 或 分支 它可以向下ab or c d e 如果你低头ab分支 你得到两个节点 a and b or a其次是b
  • 使用数据绑定,如何将包含表情符号的文本绑定到标签并使其正确显示?

    我正在编写一个应用程序来连接 WordPress BuddyPress API 该应用程序将允许用户通过 API 相互发送消息 当这些消息包含表情符号时 我很难正确显示它们 以下是 API 返回的消息文本的简短示例 Hi x1f642 ho
  • 当需要不同数量和类型的参数时如何创建操作委托列表

    我们有一组大约两打的类 它们继承自具有抽象 Validate 方法的基类 当然 每个类都有不同的验证需求 但它们之间的不同组合需要规则 因此 正如您可以想象的那样 这导致了大量代码重复 例如 A 类需要规则 1 3 6 和 9B 类需要规则
  • C#:自定义转换为值类型

    是否可以将自定义类转换为值类型 这是一个例子 var x new Foo var y int x Does not compile 是否有可能实现上述情况 我需要超载一些东西吗Foo 您将必须重载强制转换运算符 public class F
  • Gremlin.net 文本包含等效项

    我正在使用 Gremlin net 库连接到 janus 图形服务器 我使用 cassandra 和弹性搜索进行数据存储和索引 在我使用的 gremlin 语言和 gremlin 控制台中文本包含在属性的文本中进行搜索 我正在使用混合索引
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO
  • 如何从 Access 数据库中读取“是/否”值作为布尔值?

    帮我找回YES NO来自 MS Access 的布尔格式数据类型 我尝试解析它 但它总是返回 false 更新 实际上不是问题抱歉 它确实接受 YES NO 作为布尔值 OleDbconnection dbConnect new OleDb
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • 从对列表创建邻接列表类型结构

    在 C 中 我有 class Pair int val1 int val2 我有一个来自以下来源的配对列表 List
  • 为什么在构造函数中设置字段是(或不是)线程安全的?

    假设您有一个像这样的简单类 class MyClass private readonly int a private int b public MyClass int a int b this a a this b b public int

随机推荐