基本类型变量的赋值计算序列,右操作数引发异常
Computation sequence of assignment, for a variable of fundamental type, with right operand throwing an exception
如果我使用一个可能抛出的表达式来为基本类型的变量赋值,那么如果抛出异常,是否可以保证变量的状态不变?
例如,在下面的代码中,如果我们选择"选项A",并且operator new()
抛出异常,那么在堆栈展开期间调用析构函数时,成员变量ptr
是否有机会不等于nullptr
?
#include <new> // operator new operator delete
class MemoryHolder {
private:
void * ptr;
public:
MemoryHolder () {
ptr = nullptr;
}
void increase_memory () {
operator delete (ptr);
ptr = nullptr;
// Option A (unsafe?)
ptr = operator new (10);
// Option B (safe)
void * new_ptr = operator new (10);
ptr = new_ptr;
}
~MemoryHolder () {
operator delete (ptr);
}
};
我很想知道C++14和C++17的答案。
我的猜测是:"选项A"在C++14和C++17中是安全的,因为它们都包含此语句(参见§[expr.ass]¶1):
在所有情况下,赋值都是在左右操作数的值计算之后排序的
但是,我不确定执行左操作数的"值计算"是否不包括给它一个新值。我在标准中没有找到"价值计算"的定义。
相关(但我不清楚):C++中的赋值发生,尽管右侧出现异常
在下面的代码中,如果我们选择"选项A",并且
operator new()
抛出异常,那么在堆栈展开过程中调用析构函数时,成员变量ptr
是否有机会不等于nullptr
?
我会暂时忘记,ptr
在new
调用之前从未在MemoryHolder
中实际初始化,因此可能具有不确定的值。因此,您的问题是"ptr
在分配之前和分配之后的值相同吗?">
在某种程度上,你可以实际验证这一点(在构造函数中,这意味着你必须在构造函数内部捕获异常),是的,它将具有相同的值。
我在标准中没有找到"值计算"的定义。
虽然该标准有时会深入研究古怪的语言,但它并不是试图主动欺骗你。如果一个术语没有定义,那么它应该按面值计算。"价值计算"是指。。。计算该值。你把A分配给B。这意味着要弄清楚A和B都是什么。这包括为它们计算值,然后执行赋值。
相关(但我不清楚):C++中的赋值发生,尽管右侧出现异常
这与您的问题无关,因为这是关于赋值两边的"值计算"顺序,而不是关于执行赋值。那个问题的OP弄错了。任务从来没有真正发生过。只是map::operator[]
将在映射中创建一个条目(如果还不存在的话)。由于C++14不会对赋值操作的两侧进行排序,因此实现可以允许它们以任何顺序发生。在这种情况下,operator[]
首先发生,因此即使没有发生赋值,也会插入一个元素。
- 处理多个异常集合的C++方法
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- C++中的赋值发生,尽管右侧出现异常
- 控制允许动态运行c++的并发操作数
- 从构造函数抛出异常时如何克服内存泄漏
- 异常属于C++中的线程还是进程
- 当类定义不可见时捕获异常
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 为什么异常不退出程序?
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 是什么导致了Unity 3D中的"错误线程异常"?
- 如何将strftime中的格式错误作为异常捕获
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 尝试使用智能指针时引发异常
- 函数如何通知用户它基于函数原型抛出异常?
- 基本类型变量的赋值计算序列,右操作数引发异常