如何解决标记一个函数noexcept可能导致构造返回对象的异常
考虑此功能:
std::vector<unsigned> copy(std::vector<unsigned> const& v) noexcept
{ return v; }
int main()
{
try {
(void)copy({1,2,3});
} catch(...) {}
}
返回的对象的副本构造可能会抛出。在这种情况下,该异常是否会传播到调用方(即认为发生在main
中),因此将在catch(...)
处理程序中进行处理?还是该异常会遇到noexcept
并导致调用std::terminate()
?
在C ++ 17 / C ++ 20中,关于生存期规则的更改(标准化的RVO,临时实现,隐式对象创建等)相对于该标准的先前版本是否在这方面更改了一些规则?
解决方法
C ++ 17的措词更改增加了return语句周围的顺序。添加了以下段落。
[stmt.return]
3调用结果的复制初始化被排序 在临时人员被摧毁之前 由return语句的操作数建立的完整表达式, 反过来,它在销毁局部变量之前进行排序 ([stmt.jump])包含return语句的块。
初始化结果对象,然后销毁作用域中的局部变量。这意味着throw在函数的范围内。因此,此时抛出的任何异常都不在调用方。
这样,将功能标记为noexcept
会使程序终止。
RVO不会改变这一点。它只影响初始化结果对象的存储空间,但是初始化本身仍然是函数执行的一部分。
,在这种情况下,异常是否会传播到调用方(即认为发生在main中),并因此在catch(...)处理程序中进行处理?
我不同意。复制必须作为返回语句表达式的一部分在函数范围内完成。因为局部析构函数仅在返回之后才调用,并且它们在函数作用域中明确定义。
是的,C ++ 17对RVO做出了一些保证,特别是现在可以保证省略此示例:
In [48]: T2 = np.tile(p[None,:,None,None],(20,1,30,40))
In [49]: T2.shape
Out[49]: (20,10,40)
In [50]: np.allclose(T,T2)
Out[50]: True
不过,如果struct Foo{};
Foo bar(){
Foo local;
return Foo{};
// Foo:~Foo(local);
}
Foo var = bar();
抛出,该函数也不例外。所有RVO都说既没有移动也没有复制到Foo:Foo()
变量中,并且var
表达式在位置Foo{}
处构造对象。但是,在构造对象时(在函数范围内,甚至在调用析构函数之前),它也不会改变。
此外,由于var
不是prvalue而是l值,因此强制RVO在这里不适用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。