c++ - 临时数据成员的生命周期延长和API设计

标签 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;
};

parent() 成员函数返回this 路径的父路径,因此它(正确地)返回一个新构造的Path 对象代表它。

对于将操作系统级别的路径表示为 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)

这两行都很好,因为:

  • 假设 my_path 持续存在,则 s 仍然有效。
  • parent() 返回的临时对象的生命周期由 const& 延长。

到目前为止,还不错。但是,如果我有这样的代码:

std::string const &s = my_path.parent().as_utf8(); // WRONG

那么这是错误的,因为parent() 返回的临时对象没有延长了它的生命周期,因为const& 引用临时文件,而是引用它的数据成员。此时,如果您尝试使用 s,您将得到垃圾或核心转储。如果代码是:

    std::string as_utf8() const {                 // Note: object and NOT const&
        return path;
    }

那么代码就是正确的。但是,每次调用此成员函数时都创建一个临时对象是低效的。这也意味着没有“getter”成员函数应该永远返回对其数据成员的引用。

如果 API 保持原样,那么调用者必须查看 as_utf8() 的返回类型以查看它是否返回 const& 或不是:如果是,则调用者必须使用对象并且不是 const&;如果它返回一个对象,那么调用者可以使用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
}

关于c++ - 临时数据成员的生命周期延长和API设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39128193/

相关文章:

angularjs - 在完成 API Nodejs 之前提示用户警告

c++ - 对临时变量的 const 引用及其背后的机制

git - 哪些 git 命令可以删除你的 stash ?

file - 如何使用公共(public) Gradle API 创建临时文件/文件夹?

c++ - CodeChef 显示 gets() 未在任何范围内声明。虽然在 Codeblocks 上可以正常工作

c++ - 将缓冲的文本数据读入字符串

c++ - 变量的类型不完整 'ParamBlockRec'(又名 'ParamBlockRec')

Restful 设计,如何创建授权服务

c++ - 为什么必须将参数强制转换为 const?

idioms - API 设计 : is "fault tolerance" a good thing?