【问题标题】:Should methods returning const std::string& return const std::string_view instead?返回 const std::string& 的方法应该返回 const std::string_view 吗?
【发布时间】:2019-06-14 15:30:46
【问题描述】:

假设我们在一个类中有一个简单的 getter 方法,它返回一个 conststd::string 成员的引用:

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

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

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

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

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

我已经看到this 相关问题,但我要求的内容略有不同。

【问题讨论】:

    标签: c++ string c++17 string-view


    【解决方案1】:

    是的,你应该写:

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

    而不是(注意:不是const,因为永远不会返回const 值):

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

    原因是 - 你已经有一个string。因此,您无需支付任何额外费用即可从中获得string。并且string 与任意string_view 有一个显着的语义差异:保证它是null-terminated。我们知道这一点。也许一些下游用户需要依赖这些信息。如果他们需要空终止(例如,他们需要传递给一些需要它的 C API)并且您提供string_view,他们必须自己制作一个string。您什么都不保存,但可能会使下游用户做更多的工作。

    但是,如果您有一个 vector<char> 代替......那么我建议返回一个 span<char const> 或等效的。因为没有语义差异,您只是提供一个视图。


    还有what的单独参数:

    auto x = obj.getString();
    

    应该这样做。这要么获取string 的副本(昂贵,但安全),要么有效地引用它(便宜,但可能悬空)。但它看起来并不完全像一个参考,它看起来像一个值。这对于一般的引用语义类型来说是一个广泛的问题(例如reference_wrapperstring_viewspantuple<T&...>optional<T&>,如果存在的话等)。

    我没有这个案子的答案,但有一点需要注意。

    【讨论】:

    • 关于第二部分:我认为在const std::string& 的情况下,生命周期延长会起作用,这可能是你在使用string_views 时松动的东西......这可能是另一个更喜欢的论点const 引用而不是字符串视图?
    • 我已经看到了太多由于假设 std::string 为空终止而导致的错误。除非使用 c_str(),否则我建议永远不要假设。当然,它碰巧是有保证的,但是当您希望编译器捕获错误的代码进行更改时,不要高兴地给出指向 std::vector 的指针,其中有人假设 *v.end() 是指向的合法指针一个空终止符。
    • @andreee 生命周期延长只有在你的 getter 返回一个prvalue std::string getString() 时才会生效。你会有一个悬空的参考做auto& str = make_obj().getString()
    • @ZanLynx 你是什么意思? std::string guarantees null-termination on 基本上 every kind 自 C++11 以来的访问...
    • @FabioFracassi 所以右值重载返回string,左值返回string_view?不知道我对此有何感想。 (另外,嗨法比奥!)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    相关资源
    最近更新 更多