zoukankan      html  css  js  c++  java
  • forward

    Rvalue Reference 右值引用

    当赋值操作的右边是右值(rvalue),左边的对象不需要特意分配内存去存放这个拷贝(copy),而可以搬移(move)右边对象的资源。

    用于解决不必要的拷贝和实现完美转发(perfect forwarding)。

    Move Semantics 移动语义

    move 相当于 浅拷贝 + 打断原指针,原来的对象无法再使用。

     

    STL 许多地方使用到了右值引用和 move 语义,如 vector 中的 insert() 函数

    iterator insert(const_iterator pos, const value_type& x);
    iterator insert(const_iterator pos, const value_type&& x)    // 接受右值引用
    { return emplace(pos, std::move(x)); }    // 将左值变量放到std::move()中,就取得了它的右值引用
    #include<iostream>
    #include<string>
    using namespace std;
    template<typename T1, typename T2>
    void set(T1 && var1, T2 && var2){
             T1  m_var1 = std::forward<T1>(var1);
             T2 m_var2 = std::forward<T2>(var2);
    }
    
    
    void set2(string && var1, string && var2){
    }
    void set3(const string & var1, const string & var2){
    }
    int main()
    {
            string str1("hello");
            string str2("world");
            set(str1, str2);
            set("temporary str1","temporary str2");
            set3("temporary str1","temporary str2");
            //set2(str1, str2);
            return 0;
    }
     

    编译没问题

    root@ubuntu:~/c++# vi rvalue3.cpp  +21
    #include<iostream>
    #include<string>
    using namespace std;
    template<typename T1, typename T2>
    void set(T1 && var1, T2 && var2){
             T1  m_var1 = std::forward<T1>(var1);
             T2 m_var2 = std::forward<T2>(var2);
    }
    
    
    void set2(string && var1, string && var2){
    }
    void set3(const string & var1, const string & var2){
    }
    void set4(string & var1, string & var2){
    }
    int main()
    {
            string str1("hello");
            string str2("world");
            set(str1, str2);
            set("temporary str1","temporary str2");
            set3("temporary str1","temporary str2");
            set4("temporary str1","temporary str2");
            //set2(str1, str2);
            return 0;
    }
    value3.cpp: In function ‘int main()’:
    rvalue3.cpp:24:40: error: invalid initialization of non-const reference of type ‘std::__cxx11::string& {aka std::__cxx11::basic_string<char>&}’ from an rvalue of type ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
      set4("temporary str1","temporary str2");
                                            ^
    In file included from /usr/include/c++/5/string:52:0,
                     from /usr/include/c++/5/bits/locale_classes.h:40,
                     from /usr/include/c++/5/bits/ios_base.h:41,
                     from /usr/include/c++/5/ios:42,
                     from /usr/include/c++/5/ostream:38,
                     from /usr/include/c++/5/iostream:39,
                     from rvalue3.cpp:1:
    /usr/include/c++/5/bits/basic_string.h:455:7: note:   after user-defined conversion: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]
           basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
           ^
    rvalue3.cpp:15:6: note:   initializing argument 1 of ‘void set4(std::__cxx11::string&, std::__cxx11::string&)’
     void set4(string & var1, string & var2){
          ^
    #include<iostream>
    using namespace std;
    
    
    
    void process(int& i) {
        cout << "process(int&): " << i << endl;
    }
    
    void process(int&& i) {
        cout << "process(int&&): " << i << endl;
    }
    
    void forward(int&& i) {
        cout << "forward(int&&): " << i << ", ";
        process(i);
    }
    
    int main() {
        int a = 0;
        process(a);         
        process(1);         
        process(move(a));   
        forward(2);         
                            
        forward(move(a));   
        //forward(a);         
        return 0;
    }
    process(int&): 0
    process(int&&): 1
    process(int&&): 0
    forward(int&&): 2, process(int&): 2
    forward(int&&): 0, process(int&): 0
    // Rvalue经由forward()传给另一个函数却变为Lvalue,原因是传递过程中它变成了named object
    #include<iostream>
    using namespace std;
    
    
    
    void process(int& i) {
        cout << "process(int&): " << i << endl;
    }
    
    void process(int&& i) {
        cout << "process(int&&): " << i << endl;
    }
    
    void forward(int&& i) {
        cout << "forward(int&&): " << i << ", ";
        process(i);
    }
    
    int main() {
        int a=0;
        forward(a);         
        return 0;
    }
    forward.cpp: In function ‘int main()’:
    forward.cpp:21:14: error: no matching function for call to ‘forward(int&)’
         forward(a);         
                  ^
    forward.cpp:14:6: note: candidate: void forward(int&&) <near match>
     void forward(int&& i) {
          ^
    forward.cpp:14:6: note:   conversion of argument 1 would be ill-formed:
    forward.cpp:21:14: error: cannot bind ‘int’ lvalue to ‘int&&’
         forward(a);         
                  ^
    In file included from /usr/include/c++/5/bits/stl_pair.h:59:0,
                     from /usr/include/c++/5/bits/stl_algobase.h:64,
                     from /usr/include/c++/5/bits/char_traits.h:39,
                     from /usr/include/c++/5/ios:40,
                     from /usr/include/c++/5/ostream:38,
                     from /usr/include/c++/5/iostream:39,
                     from forward.cpp:1:
    /usr/include/c++/5/bits/move.h:87:5: note: candidate: template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_From>::type&&)
         forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
         ^
    /usr/include/c++/5/bits/move.h:87:5: note:   template argument deduction/substitution failed:
    forward.cpp:21:14: note:   couldn't deduce template parameter ‘_Tp’
         forward(a);         
                  ^
    In file included from /usr/include/c++/5/bits/stl_pair.h:59:0,
                     from /usr/include/c++/5/bits/stl_algobase.h:64,
                     from /usr/include/c++/5/bits/char_traits.h:39,
                     from /usr/include/c++/5/ios:40,
                     from /usr/include/c++/5/ostream:38,
                     from /usr/include/c++/5/iostream:39,
                     from forward.cpp:1:
    /usr/include/c++/5/bits/move.h:76:5: note: candidate: template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_From>::type&)
         forward(typename std::remove_reference<_Tp>::type& __t) noexcept
         ^
    /usr/include/c++/5/bits/move.h:76:5: note:   template argument deduction/substitution failed:
    forward.cpp:21:14: note:   couldn't deduce template parameter ‘_Tp’
         forward(a);         
                  ^

     使用 std::forward<T>(),保留参数的左/右值特性。

    #include<iostream>
    using namespace std;
    
    
    
    void process(int& i) {
        cout << "process(int&): " << i << endl;
    }
    
    void process(int&& i) {
        cout << "process(int&&): " << i << endl;
    }
    
    void forward(int&& i) {
        cout << "forward(int&&): " << i << ", ";
        process(std::forward<int>(i));
    }
    
    int main() {
        int a=0;
        forward(move(a));
        forward(2);      
        return 0;
    }
    root@ubuntu:~/c++# g++ -std=c++11  forward.cpp  -o  forward
    root@ubuntu:~/c++# ./forward
    forward(int&&): 0, process(int&&): 0
    forward(int&&): 2, process(int&&): 2
  • 相关阅读:
    Java泛型 E、T、K、V、N
    二维码生成,二维码中嵌套图片,文字生成图片
    线程之线程安全解决
    多线程的卖票示例来理解两种创建线程方法的区别
    多线程
    Object类
    Runtime
    9.Lambda表达式入门
    匿名内部类
    局部内部类
  • 原文地址:https://www.cnblogs.com/dream397/p/14684675.html
Copyright © 2011-2022 走看看