- 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
Guidelines - C++11, 25 of n
最新推荐文章于 2025-08-22 23:21:42 发布
本文探讨了C++中使用智能指针、STL容器等现代特性进行资源管理的最佳实践。介绍了如何通过返回局部变量值来利用返回值优化(RVO/NRVO),并避免返回常量值及引用潜在问题。同时强调了正确使用移动语义以提高效率。
1771

被折叠的 条评论
为什么被折叠?



