Guidelines - C++11, 25 of n

来源:互联网 发布:java如何实现高并发 编辑:程序博客网 时间:2024/06/06 14:04
  • Use unique_ptr, shared_ptr, vector, string to manage resources
  • Return locals by value. Don't return by const value
    Examples:
    // deprecated since C++11 because it prohibits move semantics which is faster. Good in C++98
    const string foo() { return "foo"; } 
    Fix;
    string foo() { return "foo"; }

    string bar() { 
        string ret;
        ...
         // Not good, it prohibits RVO/NRVO, moving is still expensive than RVO/NRVO.
        return move(ret); 
    }
    Fix:
    string bar() { 
        string ret;
        ...
        return ret;  
    }
    // Note, RVO/NRVO may take effective if the returning local object's type is exactly the same
    // as the function's return type (cv-qualifiers are not taken into account).
    // If for any reason, RVO/NRVO is not effective for the above case, C++11 still can take
    // "ret" as a rvalue object and move it to the destination, because the compiler knows
    // "ret" is a local object, and it is going to die, so stealing underlying data from it will not be
    // notified by others when "bar" exits.

    tuple<string, string> foo() {
        pair<string, string> p;
        ...
        return move(p); // good, returning object's type is not the same as the return type 
                                     // of the function "foo()". The compiler will do copy unless we 
                                     // explicitly do a move. RVO can't take effective here.
    }
  • Never return Rvalue Reference of a local object out of a function. Remember Rvalue Reference is still a reference. 
    // Example. The following error is very subtle.
    string&& join(string&& rv, const char* p) {
        return move(rv.append(", ").append(p));
    }
    string foo() { return "foo"; }
    const string& r = join(foo(), "bar");   // r refers to a destroyed temporary object
    Why:
    1) foo() returns a rvalue, which is passed to join() func and this rvalue is bound to "rv"
    2) when join() exits, the last reference (here is "rv") to this rvalue is gone, so this rvalue dtors.
    Fix:
    string join(string&& rv, const char* p) {
        return move(rv.append(", ").append(p));
    }
  • Don't return rvalue reference. It is extremely tricky/rare (forward, move, declval, get(tuple&&).
  • Always use "nullptr" instead of "NULL or 0"
  • Don't explicitly specify template arguments unless required, rely on template argument deduction.
    forward<T>(t) and make_shared<T>(a, b, c) is required.
    Use "make_pair(a, b)" instead of "make_pair<A, B>(a, b) by explicitly specifying the template args" because the latter may break C++11 and the invention of make_pair is using function template deduction. Sometimes use pair<A, B>(a, b).
    Example:
        int i = 0;
        int j = 0;
        auto p = make_pair<int, int>(i, j);  // can't compile in C++11,
                                                                    // note: cannot convert 'i' (type 'int') to type 'int&&'
  • URVO (Unnamed Return Value Optimization), All paths return rvalues
  • NRVO (Named Return Value Optimization), All paths return same local
    Everything else: assume an extra copy

原创粉丝点击