std::move 如何将表达式转换为右值?

2023-11-27

我不完全理解的实现std::move()。 也就是说,我对 MSVC 标准库中的这种实现感到困惑:

template<class _Ty> inline
typename tr1::_Remove_reference<_Ty>::_Type&&
move(_Ty&& _Arg)
{ // forward _Arg as movable
    return ((typename tr1::_Remove_reference<_Ty>::_Type&&)_Arg);
}

当我打电话时std::move像这样:

Object obj1;
Object obj2 = std::move(obj1); // _Ty&& _Arg binds to obj1

... the _Arg引用参数绑定到左值obj1。 您不能直接将右值引用绑定到左值,这让我认为强制转换为右值引用,例如(Object&&)是必须的。 然而,这是荒谬的,因为std::move()必须为所有价值观服务。

为了完全理解它是如何工作的,我研究了std::remove_reference too:

template<class _Ty>
struct _Remove_reference
{ // remove reference
    typedef _Ty _Type;
};

template<class _Ty>
struct _Remove_reference<_Ty&>
{ // remove reference
    typedef _Ty _Type;
};

template<class _Ty>
struct _Remove_reference<_Ty&&>
{ // remove rvalue reference
    typedef _Ty _Type;
};

不幸的是,它仍然令人困惑,我不明白。 请帮助我理解的实施std::move.


我们从 move 函数开始(我稍微清理了一下):

template <typename T>
typename remove_reference<T>::type&& move(T&& arg)
{
  return static_cast<typename remove_reference<T>::type&&>(arg);
}

让我们从更简单的部分开始 - 也就是说,当使用右值调用函数时:

Object a = std::move(Object());
// Object() is temporary, which is prvalue

and our move模板实例化如下:

// move with [T = Object]:
remove_reference<Object>::type&& move(Object&& arg)
{
  return static_cast<remove_reference<Object>::type&&>(arg);
}

Since remove_reference皈依者T& to T or T&& to T, and Object不是参考,我们最终的函数是:

Object&& move(Object&& arg)
{
  return static_cast<Object&&>(arg);
}

现在,您可能想知道:我们还需要演员阵容吗?答案是:是的,我们愿意。原因很简单;命名右值引用is被视为左值(标准禁止从左值到右值引用的隐式转换)。


这是当我们调用时会发生的情况move与左值:

Object a; // a is lvalue
Object b = std::move(a);

以及相应的move实例化:

// move with [T = Object&]
remove_reference<Object&>::type&& move(Object& && arg)
{
  return static_cast<remove_reference<Object&>::type&&>(arg);
}

Again, remove_reference皈依者Object& to Object我们得到:

Object&& move(Object& && arg)
{
  return static_cast<Object&&>(arg);
}

现在我们进入棘手的部分:什么是Object& &&甚至意味着它如何绑定到左值?

为了允许完美转发,C++11标准提供了引用折叠的特殊规则,如下:

Object &  &  = Object &
Object &  && = Object &
Object && &  = Object &
Object && && = Object &&

正如你所看到的,根据这些规则Object& &&实际上意味着Object&,这是允许绑定左值的普通左值引用。

最终函数是:

Object&& move(Object& arg)
{
  return static_cast<Object&&>(arg);
}

这与之前的右值实例化没有什么不同——它们都将其参数转换为右值引用,然后返回它。不同之处在于,第一个实例化只能与右值一起使用,而第二个实例化则与左值一起使用。


解释为什么我们需要remove_reference再多一点,让我们尝试一下这个功能

template <typename T>
T&& wanna_be_move(T&& arg)
{
  return static_cast<T&&>(arg);
}

并用左值实例化它。

// wanna_be_move [with T = Object&]
Object& && wanna_be_move(Object& && arg)
{
  return static_cast<Object& &&>(arg);
}

应用上面提到的引用折叠规则,您可以看到我们得到了无法使用的函数,如下所示move(简单来说,你用左值调用它,你就得到左值)。如果有的话,这个函数就是恒等函数。

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

std::move 如何将表达式转换为右值? 的相关文章

  • 为什么存在 async 关键字

    浏览 msdn 9 频道视频时 我发现以下未答复的评论 希望有人能解释一下 我不明白 async 关键字的意义 为什么不直接允许 任何时候方法返回任务时都会使用await关键字 就像迭代器一样 可以在任何返回 IEnumerable 的方法
  • 具有不同大小结构的结构数组的 malloc()

    如果每个结构都包含一个大小不同的字符串数组 那么如何正确地 malloc 一个结构数组 因此每个结构可能有不同的大小 并且不可能 realloc 结构体数量 sizeof 结构体名称 after malloc 初始大小 sizeof 结构名
  • 如何使用 zlib 制作 .zip 文件

    我正在阅读zlib的文档 它相当详细 但我读到了这一行 输出数据将位于zlib格式 与 gzip 或zip formats http www zlib net zlib how html http www zlib net zlib how
  • Subversion 和 Visual Studio 项目的最佳实践

    我最近开始在 Visual Studio 中处理各种 C 项目 作为大型系统计划的一部分 该系统将用于替换我们当前的系统 该系统是由用 C 和 Perl 编写的各种程序和脚本拼凑而成的 我现在正在进行的项目已经达到了颠覆的临界点 我想知道什
  • C 程序从连接到系统的 USB 设备读取数据

    我正在尝试从连接到系统 USB 端口的 USB 设备 例如随身碟 获取数据 在这里 我可以打开设备文件并读取一些随机原始数据 但我想获取像 minicom teraterm 这样的数据 请让我知道我可以使用哪些方法和库来成功完成此操作以及如
  • 从 C 结构生成 C# 结构

    我有几十个 C 结构 我需要在 C 中使用它们 典型的 C 结构如下所示 typedef struct UM EVENT ULONG32 Id ULONG32 Orgin ULONG32 OperationType ULONG32 Size
  • 如何创建用于 QML 的通用对象模型?

    我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性 例如 我有AnimalModel http doc qt io qt 5 qtquick modelviewsdata cppmodels html qabstra
  • 将字符串转换为正确的 URI 格式?

    有没有简单的方法可以将电子邮件地址字符串转换为正确的 URI 格式 Input http mywebsite com validate email 3DE4ED727750215D957F8A1E4B117C38E7250C33 email
  • 如何生成 appsettings..json 文件?

    我有一个 ASP NET Core 2 WebAPI 它将部署在以下环境中 INT QA STAGE 生产环境 基于上述 我需要有appsettings
  • 如何将带有自定义分配器的 std::vector 传递给需要带有 std::allocator 的函数?

    我正在使用外部库 pcl 因此我需要一个不会更改现有函数原型的解决方案 我正在使用的一个函数生成一个std vector
  • 劫持系统调用

    我正在编写一个内核模块 我需要劫持 包装一些系统调用 我正在暴力破解 sys call table 地址 并使用 cr0 来禁用 启用页面保护 到目前为止一切顺利 一旦完成 我将公开整个代码 因此如果有人愿意 我可以更新这个问题 无论如何
  • HttpWebRequest vs Webclient(特殊场景)

    我知道这个问题之前已经回答过thread https stackoverflow com questions 1694388 webclient vs httpwebrequest httpwebresponse 但我似乎找不到详细信息 在
  • C# 委托责任链

    为了我的理解目的 我实现了责任链模式 Abstract Base Type public abstract class CustomerServiceDesk protected CustomerServiceDesk nextHandle
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • C++11 动态线程池

    最近 我一直在尝试寻找一个用于线程并发任务的库 理想情况下 是一个在线程上调用函数的简单接口 任何时候都有 n 个线程 有些线程比其他线程完成得更快 并且到达的时间不同 首先我尝试了 Rx 它在 C 中非常棒 我还研究了 Blocks 和
  • tabcontrol selectedindex 更改事件未被触发 C#

    嘿伙计们 我有一个很小的问题 请参阅下面的代码 this is main load private void Form1 Load object sender EventArgs e tabAddRemoveOperator Selecte
  • asp.net网格分页的SQL查询

    我在用iBatis and SQLServer 使用偏移量和限制进行分页查询的最佳方法是什么 也许我添加该列ROW NUMBER OVER ORDER BY Id AS RowNum 但这只会阻止简单查询的数据访问 在某些情况下 我使用选择
  • 为什么要在 C++ 中使用 typedef?

    可以说我有 set
  • 初始化 LPCTSTR /LPCWSTR [重复]

    这个问题在这里已经有答案了 我很难理解并使其正常工作 基本上归结为我无法成功初始化这种类型的变量 它需要有说的内容7 2E25DC9D 0 USB003 有人可以解释 展示这种类型的正确初始化和类似的值吗 我已查看此站点上的所有帮助 将项目
  • 使用 HTMLAgilityPack 从节点的子节点中选择所有

    我有以下代码用于获取 html 页面 将网址设置为绝对 然后将链接设置为 rel nofollow 并在新窗口 选项卡中打开 我的问题是关于将属性添加到 a s string url http www mysite com string s

随机推荐

  • Python 中确定特定函数是否在堆栈上的有效方法

    对于调试来说 判断特定函数是否位于调用堆栈的较高位置通常很有用 例如 我们通常只想在某个函数调用我们时运行调试代码 一种解决方案是检查上方的所有堆栈条目 但如果这是在堆栈深处并重复调用的函数中 这会导致过多的开销 问题是找到一种方法 使我们
  • java在哪里寻找文件?

    我正在尝试用java读取文件 Public class Test public static void main String args throws IOException BufferedReader f new BufferedRea
  • 将 Nhibernate 查询转换为通用列表时出错

    我有一个简单的实体称为EmployeeEntity有属性ID Name Age Organisation and Designation 我只是使用查询来查询数据库 IQuery query session CreateQuery sele
  • 忽略 Powershell Invoke-RestMethod 中的自签名证书不起作用(又变了......)

    使用忽略证书验证的标准解决方案后 Invoke RestMethod正在返回 Invoke RestMethod A system error occurred and has been logged Please try again la
  • Matlab - 如何替换向量中的所有特殊字符?

    是否可以通过正则表达式替换matlab向量中的所有特殊字符 谢谢 EDIT 谢谢你的回复 我正在努力实现以下目标 我有一个文本文件 其中包含小说中的几个段落 我已将此文件读入向量 fileText Token1 token 2 token
  • 静态对象的私有析构函数是如何调用的? [复制]

    这个问题在这里已经有答案了 可能的重复 无法访问单例类析构函数中的私有成员 我正在实现一个单例 如下所示 class A public static A instance private A void cout lt lt In the c
  • 为什么需要将 ~/.rbenv/bin 添加到我的路径中?

    我读到rbenv 无法更改全局 ruby 版本我需要添加 rbenv bin到我的 PATH 以便 rbenv 工作 文中也提到了这一点rbenv 文档但该目录不存在 如下所示 ls a rbenv plugins shims versio
  • .NET 反射:检测 IEnumerable

    我正在尝试检测 Type 对象的特定实例是否是通用的 IEnumerable 我能想到的最好的办法是 theType might be typeof IEnumerable
  • Sqlplus可以将文件内容读取到变量中吗?

    我已经修改 sqlplus 一段时间了 我已经设法让 sqlplus 将文件的内容读入替换变量 如下所示 exit sqlplus s login pass db script sql cat file txt 这主要按照我的脚本要求工作
  • 使用 DirectShow.NET 从网络摄像头捕获帧

    我是 DirectShow 的新手 所以这个库的某些部分我不太理解 我已经看到示例 DxSnap 但我需要捕获帧而不预览它 进行进一步处理 我该怎么做 如果您主要关心的是 访问网络摄像头 而不是 使用 DirectShow 访问网络摄像头
  • AVPlayer 不同步

    我实在是没办法了 只好再请教大家了 我正在构建一个使用 AVPlayer 的三个实例的 iPhone 应用程序 他们同时进行比赛 这一点非常重要 我曾经运行过这段代码 CMClockRef syncTime CMClockGetHostTi
  • Paho MQTT Android 服务问题

    我正在我正在开发的应用程序中实现 Paho MQTT Android 服务 在测试了 Paho 提供的示例应用程序后 我发现有一些我想要更改的内容 https eclipse org paho clients android 一旦应用程序完
  • 如何使用动画为搜索栏添加动画

    我是安卓新手 我正在尝试为水平搜索栏设置动画 但到目前为止还无法做到 我只想要一个动画 其中搜索栏显示某个持续时间 例如 1 分钟 的进度 有人可以建议 给出关于如何为标准搜索栏设置动画的想法 代码片段吗 我应该使用哪种动画 例如 obje
  • 在 PHP 中,如何添加到零填充数字字符串并保留零填充?

    如果我在 PHP 中有一个变量包含0001我加 1 结果是 2 而不是0002 我该如何解决这个问题 foo sprintf 04d foo 1
  • 应用程序确实收到本地通知未触发 iOS 7

    问题 void application UIApplication application didReceiveLocalNotification UILocalNotification notification 有时在 iOS 7 中不会
  • 如何在 pandas groupby 中聚合多列

    我使用以下输入创建了一个 pandas 数据框 mn keyA state n1 n2 d1 d2 key1 CA 100 1000 1 2 key2 FL 200 2000 2 4 key1 CA 300 3000 3 6 key1 AL
  • R重命名函数中传递的列

    我一直在寻找这个并发现这个链接有助于重命名函数中传递的列 column name 实际制作的代码my function1在我寻找了一段时间后工作 有没有办法使用管道运算符来重命名函数内数据框中的列 我的尝试显示在my function2但它
  • Ubuntu 上的 ASP.Net Core 应用程序服务仅侦听端口 5000

    我正在尝试在 Ubuntu 服务器上托管 ASP Net Core MVC 应用程序 启用了 https 重定向 使用 Nginx 作为反向代理 我已使用 OpenSSL 创建并安装了本地 SSL 证书 当我使用 dotnet CLI 运行
  • 为什么 Web 部署代理服务监听端口 80 和 8172

    在四个 Win Server 2008 R2 机器上 我们安装了 MS Deploy 它侦听端口 80 和 8172 这使人们对网络上有关在 IIS 7 上运行时无需更改端口 80 默认值的所有其他材料产生疑问 我无法理解 为什么它使用两个
  • std::move 如何将表达式转换为右值?

    我不完全理解的实现std move 也就是说 我对 MSVC 标准库中的这种实现感到困惑 template