【问题标题】:Should I use exceptions for checking valid input?我应该使用异常来检查有效输入吗?
【发布时间】:2021-06-06 09:33:59
【问题描述】:

我正在使用gcc10.2c++20

我在学了 2 年的 python 后正在学习 c++。

在 python 中,我们总是对输入的有效性进行运行时检查

def createRectangle(x, y, width, height): # just for example
    for v in [x, y, width, height]:
        if v < 0:
            raise ValueError("Cant be negative")
    # blahblahblah

我将如何在 c++ 中进行这样的处理?

【问题讨论】:

  • raise 等效于 throw
  • if(v &lt; 0) throw std::out_of_range("Cant be negative");
  • C++ 是一种错误类型的语言,使用一些unsigned 类型作为参数,所以它们不能是负数:)
  • @Jarod42 - 这是我最近看到的最好的错字。
  • @StoryTeller-UnslanderMonica:我强壮吗? :)

标签: c++ assert c++20


【解决方案1】:
for (int v : {x, y, width, height})
    if (v < 0)
        throw std::runtime_error("Can't be negative");

请注意,这样的循环将每个变量复制两次。如果您的变量复制繁重(例如容器),请改用指针:

for (const int *v : {&x, &y, &width, &height})
    if (*v < 0)
        ...

评论还建议使用参考,例如for (const int &amp;v : {x, y, width, height}),但这仍然会为每个变量提供一份副本。所以如果一个类型那么重,我更喜欢指针。

【讨论】:

  • 这不是断言。目前尚不清楚 OP 想要什么。
  • @AyxanHaqverdili 我决定相信问题主体而不是标题。 :)
  • 改用指针 为什么??? for (const auto&amp; v : {x, y, width, height})
  • 我不确定您的“使用指针”位。
  • @NathanOliver: for (const auto&amp; v : {std::cref(x), std::cref(y), std::cref(width), std::cref(height)}).
【解决方案2】:

在 C++ 中:

  1. 使用适当的类型,因此不需要验证(在您使用变量时,而不是从某些输入中设置它们),例如unsigned 的长度。 C++ 的类型比 Python 更强,因此您不需要进行大量的验证检查来确保将正确的类型传递给函数。

  2. throw 大致相当于 Python 中的 raise。在 C++ 中,我们倾向于从 std::exception 派生一个异常,然后抛出它。

Boost (www.boost.org) 有一个不错的验证库,值得一看。

【讨论】:

  • C++ 虽然没有unsigned double ;-)(是的,我在编辑之前看到了 :-))
  • 我不同意第 1 点。使用unsigned 隐藏 错误。如果用户使用负数调用该函数,则没有很好的方法来检查他们是否犯了错误。
  • 采用无符号大小是个坏主意:wandbox.org/permlink/BkoEtG7Jy6qCmwqs。你真的不应该将它用于必须是正值。
  • 我看到operator &gt;&gt; 在这方面“坏掉了”...
  • @AyxanHaqverdili 我可以通过强制调用者做某事的方式改变一个函数,但是使用unsigned 参数并不能做到这一点。充其量,它会发出警告,并且可以忽略。 Caleth 使用gsl::narrow_cast 的建议有类似的问题,因为调用者不需要使用它。我对这个unsigned 参数的问题是该函数产生了一种根本无法保证的安全错觉。
猜你喜欢
  • 2020-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-20
  • 2021-08-13
  • 2010-09-10
相关资源
最近更新 更多