Are the days of passing const std::string & as a parameter over?

后端 未结 13 1938

I heard a recent talk by Herb Sutter who suggested that the reasons to pass std::vector and std::string by const & are largely gon

13条回答
  •  一整个雨季
    2020-11-22 17:10

    I've copy/pasted the answer from this question here, and changed the names and spelling to fit this question.

    Here is code to measure what is being asked:

    #include 
    
    struct string
    {
        string() {}
        string(const string&) {std::cout << "string(const string&)\n";}
        string& operator=(const string&) {std::cout << "string& operator=(const string&)\n";return *this;}
    #if (__has_feature(cxx_rvalue_references))
        string(string&&) {std::cout << "string(string&&)\n";}
        string& operator=(string&&) {std::cout << "string& operator=(string&&)\n";return *this;}
    #endif
    
    };
    
    #if PROCESS == 1
    
    string
    do_something(string inval)
    {
        // do stuff
        return inval;
    }
    
    #elif PROCESS == 2
    
    string
    do_something(const string& inval)
    {
        string return_val = inval;
        // do stuff
        return return_val; 
    }
    
    #if (__has_feature(cxx_rvalue_references))
    
    string
    do_something(string&& inval)
    {
        // do stuff
        return std::move(inval);
    }
    
    #endif
    
    #endif
    
    string source() {return string();}
    
    int main()
    {
        std::cout << "do_something with lvalue:\n\n";
        string x;
        string t = do_something(x);
    #if (__has_feature(cxx_rvalue_references))
        std::cout << "\ndo_something with xvalue:\n\n";
        string u = do_something(std::move(x));
    #endif
        std::cout << "\ndo_something with prvalue:\n\n";
        string v = do_something(source());
    }
    

    For me this outputs:

    $ clang++ -std=c++11 -stdlib=libc++ -DPROCESS=1 test.cpp
    $ a.out
    do_something with lvalue:
    
    string(const string&)
    string(string&&)
    
    do_something with xvalue:
    
    string(string&&)
    string(string&&)
    
    do_something with prvalue:
    
    string(string&&)
    $ clang++ -std=c++11 -stdlib=libc++ -DPROCESS=2 test.cpp
    $ a.out
    do_something with lvalue:
    
    string(const string&)
    
    do_something with xvalue:
    
    string(string&&)
    
    do_something with prvalue:
    
    string(string&&)
    

    The table below summarizes my results (using clang -std=c++11). The first number is the number of copy constructions and the second number is the number of move constructions:

    +----+--------+--------+---------+
    |    | lvalue | xvalue | prvalue |
    +----+--------+--------+---------+
    | p1 |  1/1   |  0/2   |   0/1   |
    +----+--------+--------+---------+
    | p2 |  1/0   |  0/1   |   0/1   |
    +----+--------+--------+---------+
    

    The pass-by-value solution requires only one overload but costs an extra move construction when passing lvalues and xvalues. This may or may not be acceptable for any given situation. Both solutions have advantages and disadvantages.

提交回复
热议问题