方法应该 returning const std::string& return const std::string_view 代替吗?

Should methods returning const std::string& return const std::string_view instead?

假设我们在 class 中有一个简单的 getter 方法,returns 对 std::string 成员的 const 引用:

const std::string& getString() const noexcept { return someString; }

随着 C++17 中 std::string_view 的出现,我想知道这样写是否有任何优势:

const std::string_view getString() const noexcept { return someString; }

一种方法比另一种方法 advantages/disadvantages 好吗?显然(如果我错了请纠正我)这两种解决方案肯定会比这更好:

const char* getString() const noexcept { return someString.c_str(); }

我看过 相关问题,但我要求的内容略有不同。

是的,你应该写:

const std::string& getString() const noexcept { return someString; }

而不是(注意:不是 const,因为从来没有 return const 值):

std::string_view getString() const noexcept { return someString; }

原因是 - 您已经有一个 string。因此,您无需支付任何额外费用即可获得 stringstring 与任意 string_view 有一个显着的语义差异:保证是 null-terminated。我们知道这一点。也许某些下游用户需要依赖该信息。如果他们需要 null-termination(例如,他们需要传递给需要它的某个 C API)并且你给出 string_view,他们必须一个string自己出来吧。你没有节省任何东西,但可能会让下游用户做更多的工作。

但是,如果您使用的是 vector<char>... 那么我会建议 return 使用 span<char const> 或其等价物。由于没有语义差异,您只是提供一个视图。


还有what的单独参数:

auto x = obj.getString();

应该做的。这要么获取 string 的副本(昂贵,但安全),要么有效地引用它(便宜,但可能悬而未决)。但它看起来并不完全像一个引用,它看起来像一个值。这是一般 reference-semantic 类型的一个广泛问题(如 reference_wrapperstring_viewspantuple<T&...>optional<T&>,如果它存在,等)。

对于这种情况,我没有答案,但需要注意这一点。