• 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就已经不存在了,此处才发生了真正的移动操作。

  • 相关阅读:
    Jboss下jaxws的开发
    Jboss as 服务器基本设置
    classloader常见问题总结
    Servlet容器 Jetty
    Jetty 的工作原理以及与 Tomcat 的比较
    resin设置jvm参数
    Solr4.0使用
    Solr 4.0部署
    Solr 搜索功能使用
    HttpSolrServer 实例管理参考,来自org.eclipse.smila.solr
  • 原文地址:https://www.cnblogs.com/gezi/p/12574054.html
Copyright © 2020-2023  润新知