c++ - 需要空终止的 string_view

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

在以下场景中使用 std::string_view:

struct A : public std::exception{
    A (const char* c) : v_(c){}
    const char* what() const noexcept override;

private:
    std::string_view v_;
};

上面的想法工作正常,现在复制构造函数默认为 noexcept(这对于异常类型来说非常好!)——并且字符串也在调用站点“验证”。

然而,剩下的事情是语义上 string_view 不保证为零终止(尽管在这种情况下我们编写代码,所以它会是 - 如果那是最好的保证针对这种特殊情况,就像它只有我们实际使用的构造函数一样。

我在考虑像下面这样的事情是否是一个好的解决方法?

struct c_string_view {
  c_string_view(const char* c) : sv_{c}{};
  const std::string_view sv_;
};

但我想知道是否还有其他人遇到过这个问题(以及他们做了什么),或者我是否忽略了一些简单的事情?

最佳答案

Im considering if something like the following be a good work-around ?

Const 成员通常是有问题的。它们阻止了可分配性,并且阻止了移动构造。也就是说,异常类型可能并不总是需要可分配性,而且所讨论的类速度很快,无论如何都不需要复制。

所以在这种情况下缺点可能不那么显着,但优点也不是。您的类在构造函数中已经有空终止的前置条件,并且访问被封装到 A 的成员函数(和 friend )。


然而,更根本的是,您的异常类很容易被滥用。考虑以下典型场景:

throw A(some_local_string.c_str());

char local_buffer[N];
// fill local_buffer with formatted message
throw A(local_buffer);

这些会导致未定义的行为。

Why is that more prone to misuse than eg. std::string_view

实际上是 std::string_view 的使用使您的异常类容易被误用。存储 const char* 会遇到同样的问题。

std::string_view(和 const char*)适用于函数参数,例如,当函数存储 View 的时间不超过该功能存在。但异常几乎完全被使用,因此它们比它们的调用者活得更久,因为它们几乎总是被抛出,这让调用者放松。

if I/we had c_string_view from the get go - we could just use that in the constructor instead of const char* to show intent as well.

接受 c_string_view 并不能真正解决问题,因为它本身并不意味着它将比 const char* 存储更多。您能做的最好的事情是记录如何使用该类,当这些使用排除异常使用的常见模式时,这有点不令人满意。

也许如果您将类命名为 static_string_exception 或类似名称以使限制更加明显。


from commenters:

I'd just take an store a std::string ...

.. you should rather use good 'ol std::string

std::string 也不是理想的解决方案。它将防止复制构造函数/赋值不抛出(不严格地说,但其他替代方案是程序终止),这对异常类型不利。例如,标准异常类型不允许有抛出复制构造函数/赋值。

一旦您到达复制路径,您不妨使用 std::runtime_error 为您完成。

关于c++ - 需要空终止的 string_view,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58450978/

相关文章:

c++11 - 在这种情况下,我们应该到处使用 noexcept 吗?

c++ - 是否有自动 noexcept 说明符?

c++ - 如何使用某种统计方法匹配软聚合特征(眼睛、 Nose 、嘴巴)?

c++ - 无法从 map 获取 key_type

c++ - 重构我的代码。我的标题(Header Guard Issues)

C++ 原子列表容器

c++ - SFINAE 检测 CTAD 演绎指南的明确性

c++ - Consexpr if 具有非 bool 条件

c++ - 为什么编译器会在提供无参数函数模板时尝试推断?

c++ - 带有 "noexcept"构造函数的程序被 gcc 接受,被 clang 拒绝