zoukankan      html  css  js  c++  java
  • c++11的 move并没有实际move

    c++11的 move并没有实际move

      首先看第一个例子:

     1 #include <iostream > // std::cout
     2 #include <utility > // std::move
     3 #include <vector > // std::vector
     4 #include <string > // std::string
     5 
     6 int main() {
     7 
     8     std::string str = "Hello world.";
     9     std::vector <std::string > v;
    10 
    11     // 将 使 用 push_back(const T&), 即 产 生 拷 贝 行 为
    12     v.push_back(str);
    13     // 将 输 出 "str: Hello world."
    14     std::cout << "str: " << str << std::endl;
    15 
    16     // 将 使 用 push_back(const T&&), 不 会 出 现 拷 贝 行 为
    17     // 而 整 个 字 符 串 会 被 移 动 到 vector 中, 所 以 有 时 候 std::move 会 用 来 减 少 拷 贝 出现 的 开 销
    18     // 这 步 操 作 后 , str 中 的 值 会 变 为 空
    19     v.push_back(std::move(str));
    20     // 将 输 出 "str: "
    21     std::cout << "str: " << str << std::endl;
    22 
    23     return 0;
    24 }

    最后打印为"str: ",和我一开始理解的move语义一致,str被移入了vector中,所以str为空。

    再看下一段代码,这是在讲完美转发时的一个例子:

     1 # include <iostream >
     2 # include <utility >
     3 void reference ( int & v) {
     4     std :: cout << " 左 值 引 用 " << std :: endl ;
     5 }
     6 void reference ( int && v) {
     7     std :: cout << " 右 值 引 用 " << std :: endl ;
     8 }
     9 template <typename T>
    10 void pass (T&& v) {
    11     std :: cout << " 普 通 传 参 :";
    12     reference (v);
    13     std :: cout << " std :: move 传 参 :";
    14     reference (std :: move (v));
    15     std :: cout << " std :: forward 传 参 :";
    16     reference (std :: forward <T >(v));
    17 }
    18 
    19 int main () {
    20     std :: cout << " 传 递 右 值 :" << std :: endl ;
    21     pass (1);
    22 
    23     std :: cout << " 传 递 左 值 :" << std :: endl ;
    24     int v = 1;
    25     pass (v);
    26 
    27     return 0;
    28 }

    输出结果为:

    值 :
    参 :
    std :: move 参 :
    std :: forward 参 :
    值 :
    参 :
    std :: move 参 :
    std :: forward 参 :

     令我困惑的是,在pass中,v明明先调用了reference (std :: move (v));然后又调用了一次reference (std :: forward <T >(v));

    那么v不应该在第一次move后就已经被移走了吗?

    答案是no。

    我们看一下move的实现:

    1 template <class _Ty>
    2 _NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) noexcept { // forward _Arg as movable
    3     return static_cast<remove_reference_t<_Ty>&&>(_Arg);
    4 }

    也就是说move仅仅只是做了个类型转换,将其转为右值引用类型,并未实际发生移动效果。

    而前面第一个例子中的push_back中,实际触发了string的移动构造,导致str被真正移走。

    所以,为验证这个想法,只需要简单修改第二个例子就可以验证:

     1 # include <iostream >
     2 # include <utility >
     3 int reference(int& v) {
     4     std::cout << " 左 值 引 用 " << std::endl;
     5     return v;
     6 }
     7 int reference(int&& v) {
     8     std::cout << " 右 值 引 用 " << std::endl;
     9     return std::move(v);
    10 }
    11 
    12 template <typename T>
    13 void pass(T&& v) {
    14     std::cout << " 普 通 传 参 :";
    15     reference(v);
    16     std::cout << " std :: move 传 参 :";
    17     int a= reference(std::move(v));
    18     std::cout << " std :: forward 传 参 :";
    19     int b = reference(std::forward <T >(v));
    20 }
    21 
    22 int main() {
    23     std::cout << " 传 递 右 值 :" << std::endl;
    24     pass(1);
    25 
    26     std::cout << " 传 递 左 值 :" << std::endl;
    27     int v = 1;
    28     pass(v);
    29 
    30     return 0;
    31 }

    pass(1)时,v未被移走,而用下面int v = 1传递时,在执行完int a= reference(std::move(v));之后,v就已经不存在了,此处才发生了真正的移动操作。

  • 相关阅读:
    Maximum execution time of 30 seconds exceeded解决错误方法
    php 获取随机数的几个方式
    php header utf8 插入header("Content-type: text/html; charset=utf-8");
    php mysqli query 查询数据库后读取内容的方法
    win7 xampp 验证码,session出不来的问题
    apache 中 ServerAlias让多个域名绑定到同一空间
    最近很火的一条成长公式,看看你属于那一条!
    用crontab执行shell把top命令按日期追加到文件
    php CI 实战教程第一季百度经验杂志
    php 截取字符串第一个字符,截取掉字符串最后一个字符的方法
  • 原文地址:https://www.cnblogs.com/gezi/p/12574054.html
Copyright © 2011-2022 走看看