clang-tidy警告:在函数中可能会抛出异常。

huangapple go评论118阅读模式
英文:

clang-tidy warning: an exception may be thrown in function

问题

clang-tidy 发出以下警告:

警告:在函数 'name' 中可能会抛出异常,但该函数应该不会抛出异常 [bugprone-exception-escape]
[[nodiscard]] auto NodeData::name() const noexcept -> std::string {

在这种情况下,函数是否可以抛出异常是正确的吗?如果是的话,是什么情况?

英文:

Having this code (mName is a member of type std::string)

//.h
[[nodiscard]] auto name() const noexcept -> std::string;

and

// .cpp
[[nodiscard]] auto NodeData::name() const noexcept -> std::string {
  return mName;
}

clang-tidy is giving the following warning:

warning: an exception may be thrown in function 'name' which should not throw exceptions [bugprone-exception-escape]
[[nodiscard]] auto NodeData::name() const noexcept -> std::string {

Is it right that the function can throw exceptions in this case? If yes, what is that case?

答案1

得分: 1

由于您通过值返回一个std::string对象,将会调用std::string的复制构造函数,该构造函数不是noexcept的,因为它可能引发异常(内存分配失败)。

英文:

As you return a std::string object by value, you will invoke the copy-constructor of std::string which is not noexcept, as it may throw (failing memory allocation).

答案2

得分: 1

Clang-tidy在这种情况下是正确的。当返回std::string时,这种情况下会使用复制构造函数,可能会导致std::bad_alloc被抛出。这种情况可能性非常小,但在技术上是可能的。

如果您正在使用C++17,除了移除noexcept之外,一个可能的解决方案是将结果类型改为std::string_view

// 注意:在C++17之前,考虑将const std::string&作为结果
[[nodiscard]] auto name() const noexcept -> std::string_view;

构造一个std::string_view不涉及堆分配,因此可以安全地将此函数标记为noexcept。然而,由于视图不拥有字符串数据,您必须确保在字符串超出范围后不再使用该视图。

一般来说,您应该认真考虑是否真的需要getter和setter。正如您所看到的,getter会增加问题,例如:

  • getter分配内存并可能引发异常,或者
  • 必须仔细考虑生命周期,或者
  • 使用引用计数(这并不便宜,可能会引入内存泄漏)

也许最好的解决方案是根本不使用getter,在C++中这是完全有效的。

英文:

Clang-tidy is correct in this case. When returning std::string by value, the copy constructor is used in this case, which possibly results in std::bad_alloc being thrown. It is highly unlikely, but technically possible.

If you are using C++17, a possible solution (besides removing noexcept) is to use std::string_view as the result type instead:

// note: prior to C++17, consider const std::string& as a result
[[nodiscard]] auto name() const noexcept -> std::string_view;

The construction of a std::string_view involves no heap allocations, making it safe to mark this function noexcept. However, since the view doesn't own the string data, you would have to make sure that you don't use the view after the string goes out of scope.

In general, you should seriously consider whether you need getters/setters at all. As you can see, getters add problems such as:

  • getters allocating memory and possibly throwing, or
  • having to think carefully about lifetimes, or
  • using reference counting (which isn't cheap, and can introduce memory leaks)

Perhaps the best solution is not to use a getter at all, which is perfectly valid in C++.

huangapple
  • 本文由 发表于 2023年8月10日 21:37:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76876272.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定