Pau*_*cas 8 c++ api-design temporary data-members
假设我有一个跨平台Path类,如:
class Path {
public:
// ...
Path parent() const; // e.g., /foo/bar -> /foo
std::string const& as_utf8() const {
return path;
}
private:
std::string path;
};
Run Code Online (Sandbox Code Playgroud)
所述parent()成员函数返回的父路径this的路径,所以它(正确)返回一个新构造的Path对象,它表示它.
对于将OS级别的路径表示为UTF-8字符串(例如,Unix)的平台,将as_utf8()引用直接返回到内部表示似乎是合理的,path因为它已经是 UTF-8.
如果我有以下代码:
std::string const &s = my_path.as_utf8(); // OK (as long as my_path exists)
// ...
Path const &parent = my_path.parent(); // OK (temporary lifetime extended)
Run Code Online (Sandbox Code Playgroud)
这两行都很好,因为:
my_path持续存在,那么s仍然有效.parent()由const&.到现在为止还挺好.但是,如果我有以下代码:
std::string const &s = my_path.parent().as_utf8(); // WRONG
Run Code Online (Sandbox Code Playgroud)
那么这是错误的,因为返回的临时对象parent()并没有有它的寿命延长,因为const&它不是指的是暂时的,而到它的数据成员.此时,如果您尝试使用s,您将获得垃圾或核心转储.如果代码是:
std::string as_utf8() const { // Note: object and NOT const&
return path;
}
Run Code Online (Sandbox Code Playgroud)
然后代码是正确的.但是,每次调用此成员函数时创建临时文件都是低效的.言下之意也是没有 "消气"成员函数应不断回到自己的数据成员的引用.
如果API保持原样,那么它似乎会给调用者带来不必要的负担,必须查看返回类型as_utf8()以查看它是否返回const&:如果是,则调用者必须使用对象而不是一个const&; 如果它返回一个对象,那么调用者可以使用a const&.
那么有什么方法可以解决这个问题,这样API在大多数情况下都是高效的,但却阻止用户从看似无害的代码中获取悬空引用?
顺便说一句,这是使用g ++ 5.3编译的.这有可能是暂时的寿命应该延长,但是编译器有一个错误.
你可以做的是创建2个不同的版本as_utf8(),一个用于左值,一个用于右值.但是你需要C++ 11.
这样,你可以获得两全其美:const&当对象不是临时对象时,以及当对象不是临时对象时有效移动:
std::string const& as_utf8() const & {
// ^^^ Called from lvalues only
return path;
}
std::string as_utf8() const && {
// ^^^^ Called from rvalues only
return std::move(path); //We don't need path any more
}
Run Code Online (Sandbox Code Playgroud)