C ++ noexcept为一个函数不抛出异常,但可能导致内存故障 [英] C++ noexcept for a function not throwing exceptions, but can cause a memory failure

查看:191
本文介绍了C ++ noexcept为一个函数不抛出异常,但可能导致内存故障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,使用两种不同的方式访问私有数组的元素,重载数组下标运算符或在上定义,很常见:

For example, it's pretty common to have two separate ways to access elements of a private array, overloading the array subscripting operator, or defining at:

T& operator[](size_t i) { return v[i]; }
T const& operator[](size_t i) const { return v[i]; }

T& at(size_t i)
{
     if (i >= length)
         throw out_of_range("You shall not pass!");

     return v[i];
}

T const& at(size_t i) const
{
     if (i >= length)
         throw out_of_range("You shall not pass!");

     return v[i];
}

可以抛出异常,但数组下标运算符不能。

The at version can throw an exception, but the array subscripting operator can't.

我的问题是,运算符[] 不抛出异常,可以标记为 noexcept ,即使知道它可以产生一个SIGSEGV信号,或者它只是一个不好的做法?

My question is, altough the operator[] doesn't throw an exception, can it be marked as noexcept even knowing it can raise a SIGSEGV signal, or is it only a bad practice?

我想指出一个信号(如SIGSEGV)不是一个例外。按照字面解释 noexcept 的意思,一个 noexcept 函数声称它不会抛出异常。

I want to point out a signal (as SIGSEGV) is not an exception. Being literal interpreting the noexcept meaning, a noexcept function is one that claims it won't throw exceptions. It says nothing about anything else (including signals).

但是, noexcept 函数有更多的意义,至少对我的代码的客户端。 noexcept 也隐含地说该函数是安全的,它将完成其执行而不会有计算错误。

But, a noexcept function has more meaning than that, at least for clientes of my code. noexcept also implicitly says the function is safe and it will finish its execution without computational errors.


So, is it inappropiate to mark noexcept a function which isn't safe?

推荐答案

noexcept 这是一个棘手的问题,并提出了 noexcept中包含的一些关键问题- 做什么的?从
Andrzej的C ++博客
,它说,我将尝试引用最小值这里(强调我):

This is a tough question and brings up some of the key issues covered in noexcept — what for? from Andrzej's C++ blog which says, I will attempt to quote the minimum here (emphasis mine):


在这篇文章中,我想分享我的观察,在哪里使用noexcept真的增加了价值。它不如预期的那么频繁,它与抛出或不抛出异常没有多大关系。结论让我吃惊了一点,我犹豫提出它,因为它是反对我从我认为当局对这个问题的人的意见。

In this post I would like to share my observation on where using noexcept really adds value. It is less often than what one might expect, and it does not have that much to do with throwing or not throwing exceptions. The conclusion surprises me a bit, and I hesitate to present it because it is counter to the advice I hear from people I consider authorities on the subject.

和:


对noexcept的态度,可以认为是有用的吗?是。 noexcept特性在C ++ 11中很晚才引入,以解决移动语义的一个特定问题。这里由道格拉斯·格雷戈尔和大卫亚伯拉罕描述。

Given this negative attitude to noexcept, can it be considered useful at all? Yes. The noexcept feature was introduced very late into C++11 to address one particular issue with move semantics. It has been described here by Douglas Gregor and David Abrahams.

然后他继续给出一个不寻常的移动赋值定义,并认为我们真正想传达的不是它不抛出异常,但它不会失败,但这是非常困难的问题,但它是真正的意图:

and then he goes on to given an unusual move assignment definition and argues that what we really want to convey is not that it does not throw exceptions but that it does not fail, but that is very difficult problem but it is out real intent:


[...]是因为noexcept真正意图给
的信息是函数永远不会失败;不是从来没有投掷!我们
可以看到上面的函数可以失败,但仍然不抛出,但它
仍然符合noexcept(false)。也许关键字应该有
被称为nofail。永远不会失败的保证不能由
编译器检查(很像其他故障安全保证),因此
只有我们可以做的是声明它。

[...]This is because the information that noexcept really is intended to convey is that the function never fails; not that it never throws! We can see above that a function can fail but still not throw, but it still qualifies for noexcept(false). Perhaps the keyword should have been called nofail. The never-fail guarantee cannot be checked by the compiler (much like any other failure-safety guarantee), therefore the only thing we can do is to declare it.

这是一个更一般的观察的一部分,我们是
感兴趣的是真正的故障安全程序组件,而不是
比异常安全。无论是否使用异常,错误返回
值,errno或什么

This is part of a more general observation, that what we are interested in is really failure safety in program components rather than exception safety. No matter if you use exceptions, error return values, errno or what

其他,关于基本(无泄漏,不变量保留),强提交或回滚)和永不失败保证应该仍然保持。

ever else, the reasoning about basic (no leak, invariant preserved), strong (commit or rollback) and never-fail guarantee should still hold.

所以如果我们采取类似的位置,是不是,如果不适合使用 noexcept ,这似乎是你在哪里倾斜。我不认为这是明确的答案。

So if we take a similar position then, it would seem the answer is no, if not appropriate to use noexcept and that seems to be where you are leaning. I don't think it is clear cut answer.

他还注意到提案N3248:noexcept
防止库验证
。这反过来又是 N3279:保守使用的基础在图书馆中的noexcept 。本文定义了狭窄和宽泛的约束,如同N3248:

He also notes proposal N3248: noexcept Prevents Library Validation. Which in turn was the basis for N3279: Conservative use of noexcept in the Library. This paper defines narrow and wide conrtacts as did N3248:


广域合约

一个函数或操作的宽合约不会
指定任何未定义的行为。这样的契约没有前提条件:
具有宽合同的函数不会对其参数,任何对象状态或任何外部
全局状态的额外运行时
约束。具有宽合同的函数的例子是
vector :: begin()和vector :: at(size_type)。不具有广泛合同的
函数的示例是vector :: front()和
vector :: operator [](size_type)。

A wide contract for a function or operation does not specify any undefined behavior. Such a contract has no preconditions: A function with a wide contract places no additional runtime constraints on its arguments, on any object state, nor on any external global state. Examples of functions having wide contracts would be vector::begin() and vector::at(size_type) . Examples of functions not having a wide contract would be vector::front() and vector::operator[](size_type) .

缩小合同

缩小合约是指不宽的合约。
函数或操作的狭义合同在以违反已记录合同的
方式调用时会导致未定义的行为。这样的合约
指定至少一个涉及其参数,对象
state或一些外部全局状态的前提条件,例如
静态对象的初始化。具有窄
合同的标准函数的好例子是vector :: front()和vector :: operator [](size_type)

A narrow contract is a contract which is not wide. Narrow contracts for a functions or operations result in undefined behavior when called in a manner that violates the documented contract. Such a contract specifies at least one precondition involving its arguments, object state, or some external global state, such as the initialization of a static object. Good examples of standard functions with narrow contracts are vector::front() and vector::operator[](size_type) .

并建议:


每个库函数具有广泛的合约,LWG同意
,应标记为无条件noexcept。

Each library function having a wide contract, that the LWG agree cannot throw, should be marked as unconditionally noexcept.

,并暗示具有狭窄合同的函数不应为 noexcept ,其由 LWG问题2337 ,它说:

and implies that functions with narrow contracts should not be noexcept, which is backed up by LWG issue 2337 which says:


[...]这些设计考虑重写了我们的一般政策反对noexcept功能。 [...]

[...]These design considerations override our general policy against noexcept for narrow-contract functions. [...]

所以如果我们想保守,遵循标准库实践, > operator [] 没有宽泛的合约,不应标记为 noexcept

So if we want to be conservative and follow standard library practice then it would seem since operator[] does not have a wide contract it should not be marked noexcept.

这篇关于C ++ noexcept为一个函数不抛出异常,但可能导致内存故障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆