C++ 什么是“;noexcept表达式的计算结果为‘;假’;因为打电话到…”;?
考虑以下示例:C++ 什么是“;noexcept表达式的计算结果为‘;假’;因为打电话到…”;?,c++,C++,考虑以下示例: #include <chrono> using T = std::chrono::system_clock::time_point; struct A { A() = default; explicit A(T time) : time{time} { } T time{}; }; A foo() { return A{}; } #包括 使用T=std::chrono::system\u clock::time\u point; 结构
#include <chrono>
using T = std::chrono::system_clock::time_point;
struct A
{
A() = default;
explicit A(T time) : time{time}
{
}
T time{};
};
A foo()
{
return A{};
}
#包括
使用T=std::chrono::system\u clock::time\u point;
结构A
{
A()=默认值;
显式A(T时间):时间{time}
{
}
T时间{};
};
阿福()
{
返回一个{};
}
当我使用GCC 9.2.0编译此代码时,它将生成以下警告:
$ g++ -c noexcept.cpp -o noexcept.cpp.o --std=c++17 -Wnoexcept
noexcept.cpp:18:12: warning: noexcept-expression evaluates to ‘false’ because of a call to ‘constexpr std::chrono::time_point<_Clock, _Dur>::time_point() [with _Clock = std::chrono::_V2::system_clock; _Dur = std::chrono::duration<long int, std::ratio<1, 1000000000> >]’ [-Wnoexcept]
18 | return A{};
| ^
$g++-c noexcept.cpp-o noexcept.cpp.o--std=c++17-Wnoexcept
noexcept.cpp:18:12:警告:noexcept表达式计算结果为“false”,因为调用了“constexpr std::chrono::time\u point::time\u point()[with _Clock=std::chrono:::_V2::system\u Clock;_Dur=std::chrono::duration]”[-Wnoexcept]
18 |返回{};
| ^
我不明白这个警告的意思。它仅在第二个构造函数就位时生成(即使从未调用它)
警告涉及正在求值的noexcept表达式。因为我没有看到任何这样的表达式,所以我假设在第一个构造函数中有类似于隐式noexcept表达式的东西。但我不明白为什么那样的事情会导致警告。如果有第二个构造函数,为什么会有区别呢
你能解释一下这个代码的问题吗?我觉得这是一个假阳性诊断。因为确实没有任何noexcept表达式会因为该函数而计算为false
另外,如果我从
A::time
中删除默认成员初始值设定项,则不会重现该行为。据我所知,这在示例程序中没有语义差异。似乎您明确选择了-Wnoexcept
。此处解释了标志的含义:
当noexcept表达式由于调用没有非抛出异常规范(即throw()或noexcept)但编译器已知从未抛出异常的函数而计算为false时发出警告
在这种情况下,我不得不猜测编译器正在隐式地计算一个包含T{}
的noexcept表达式,以确定a
的默认构造函数是否应该隐式声明noexcept
。出现警告是因为编译器可以确定time\u point
的默认构造函数从不抛出,但所述默认构造函数未声明为noexcept
。看
您的代码没有问题。警告的根本原因是
time\u point
没有相应的noexcept
声明。但是,对于许多标准库构造函数来说,这是正确的,修复所有这些构造函数需要很长时间。因此,与此同时,这一警告似乎主要增加了噪音。如果仍要使用此标志进行编译,可以将A::A()
自己定义为A()noexcept{}
。(在本例中,您不会放弃琐碎性,因为t::t()
无论如何都不是琐碎的。)除了默认构造函数之外,复制构造函数是否还默认或显式指定为a(const a&a)noexcept:time(a.time){}
(带或不带noexcept)。据我理解,这两者之间应该没有区别。我是不是误解了什么,或者这是怎么发生的?@n314159同样的问题。如果复制构造函数是默认的,编译器将查看为成员和基选择的复制构造函数,以便计算隐式异常规范。啊,我想现在我明白了。只有当编译器必须猜测构造函数是否应为noexcept时,才会出现警告,因此,如果我告诉编译器构造函数是否应为noexcept,即使生成的代码应相同,也很重要。感谢您的解释!由于您提到的问题,我选择暂时禁用警告。