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

后端 未结 13 1806

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:27

    Herb Sutter is still on record, along with Bjarne Stroustroup, in recommending const std::string& as a parameter type; see https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rf-in .

    There is a pitfall not mentioned in any of the other answers here: if you pass a string literal to a const std::string& parameter, it will pass a reference to a temporary string, created on-the-fly to hold the characters of the literal. If you then save that reference, it will be invalid once the temporary string is deallocated. To be safe, you must save a copy, not the reference. The problem stems from the fact that string literals are const char[N] types, requiring promotion to std::string.

    The code below illustrates the pitfall and the workaround, along with a minor efficiency option -- overloading with a const char* method, as described at Is there a way to pass a string literal as reference in C++.

    (Note: Sutter & Stroustroup advise that if you keep a copy of the string, also provide an overloaded function with a && parameter and std::move() it.)

    #include 
    #include 
    class WidgetBadRef {
    public:
        WidgetBadRef(const std::string& s) : myStrRef(s)  // copy the reference...
        {}
    
        const std::string& myStrRef;    // might be a reference to a temporary (oops!)
    };
    
    class WidgetSafeCopy {
    public:
        WidgetSafeCopy(const std::string& s) : myStrCopy(s)
                // constructor for string references; copy the string
        {std::cout << "const std::string& constructor\n";}
    
        WidgetSafeCopy(const char* cs) : myStrCopy(cs)
                // constructor for string literals (and char arrays);
                // for minor efficiency only;
                // create the std::string directly from the chars
        {std::cout << "const char * constructor\n";}
    
        const std::string myStrCopy;    // save a copy, not a reference!
    };
    
    int main() {
        WidgetBadRef w1("First string");
        WidgetSafeCopy w2("Second string"); // uses the const char* constructor, no temp string
        WidgetSafeCopy w3(w2.myStrCopy);    // uses the String reference constructor
        std::cout << w1.myStrRef << "\n";   // garbage out
        std::cout << w2.myStrCopy << "\n";  // OK
        std::cout << w3.myStrCopy << "\n";  // OK
    }
    

    OUTPUT:

    const char * constructor
    const std::string& constructor
    
    Second string
    Second string
    

提交回复
热议问题