超载后增量
Overloading postincrement
假设我们有一个类myClass
存储一个int
。我想重载标准运算符,如+
、=
、+=
、++
等。如何重载后缀增量,即operator++(int)
,以便在计算表达式后进行实际增量?我的意思是,在执行了以下代码之后,
myClass object1(0), object2(1);
object1 = object2++ + object2;
我希望对象1和对象2都保持2。
的幼稚方法
myClass& operator++(int){
myClass tmp(x) //x - stored value
++x;
return tmp;
}
不起作用,因为++
是在+
之前调用的。
我一直在寻找答案,但没有找到任何相关的答案。坦率地说,直到最近我才认为这是可能的。
您的代码:
myClass object1(0), object2(1);
object1 = object2++ + object2;
根据§8.3.6/9:,具有实际未指明的行为
函数参数的求值顺序未指定。
由于这个表达式被转换为类似的东西
operator=(objec1, operator+(operator++(.., object2), object))
避免这种不便的明显方法是在总和之后执行增量:
object1 = object + object2;
object++;
或者(假设operator*
也被定义(:
object1 = object2 * 2;
object++;
根据§1.9/15:,如果它们是标量类型,则将是未定义的行为
除非另有说明,否则单独运算符的操作数和单独表达式的子表达式的求值都是无序列的。[注:在程序执行过程中多次求值的表达式中,其子表达式的未排序和不确定排序的求值不需要在不同的求值中一致执行。--结束语]运算符的操作数的值计算是在运算符结果的值计算之前排序的。如果一个标量对象上的副作用相对于同一标量对象上另一个副作用或使用相同标量对象的值进行的值计算是未排序的,并且它们不可能并发(1.10(,则行为是未定义的。
正如评论中所提到的,这是一个糟糕的想法,因为代码的语义与operator++
正常工作的语义不匹配,所以其他查看代码的人,甚至可能是以后的自己,都会感到困惑。
要做到这一点,您需要使用一种名为表达式模板的技术。这并不简单,但基本思想是operator++
和operator+
(以及任何其他运算符(将返回一个新类型的对象(比如Myclass_expr
(,并且该对象在执行过程中构建一个表达式;所以CCD_ 15的结果将是一个小树,上面写着"这个表达式意味着把x加到x上,然后增加x"。还没有进行实际运算。
最后,Myclass_expr
将具有一个到Myclass
的转换运算符,该运算符包含遍历存储表达式并按所需顺序执行所有计算的逻辑。
要查看此示例,请查看特征矩阵库。
好吧,我找到了一种丑陋但简单的方法,所以我将它发布给子孙后代。我在myClass
中添加了一个myClass * ptr
字段。它通常存储nullptr
,但operator++(int)
返回的对象除外。在这种情况下,ptr
存储一个指向应该递增的对象的指针。我还修改了析构函数,以便在临时对象被析构函数时执行增量:
myClass& operator++(int){
myClass tmp(x);
tmp.ptr = this;
return tmp;
}
~myClass(){
if(ptr != nullptr)
++ptr->x;
}
虽然它不是标准化的,但tmp
通常在达到分号时被破坏,即当执行x++ + x + x;
时,在计算和之后进行增量。
myClass object1(0), object2(1);
object1 = object2++ + object2;
类似于:
int i1 = 0; i2 = 1;
i1 = i2++ + i2;
这不能保证产生确定性值。CCD_ 25和CCD_ 26的评估不能保证从左到右。根据最先求值的对象,该表达式的RHS可以求值为3
或2
。
您应该重新思考您的代码。
成功:
object1 = object2;
object1 += (object2++);
或
object1 = (object2++);
object1 += object2;
这取决于你的意图。
- 寻找地理和伤害意味着超载
- 没有可行的超载'='用于shared_ptr
- "专业化不参与超载"
- 虚拟超载运算符>>和<<
- 为什么我的超载"+"运算符返回的总额错误?
- C++ 超载 += 用于两个袋子的合并,返回类型为空隙
- C++11 中对超载'ref(Select::Expressions::Code&)'的调用模棱两可
- 为什么STD :: SPAN超载函数调用操作员索引
- C 操作员超载调用驱动器
- C const char *评估操作员超载
- 如何包括C 模板类的非成员运算符 - 超载
- 类型长的长度和未解决的超载函数类型的类型的操作数与二进制运算符
- 无法调用纯抽象基类超载
- 二进制超载操作员=
- 操作员超载;必须是二进制操作员(具有3个参数)
- 如果我具有调用其其他实例之一的超载函数,它是否被认为是递归功能
- 超载 =具有多个术语的运算符
- GLM超载操作员用于地图不起作用
- C bool表达式作为函数参数调用错误的超载
- 运算符超载的Lambda表达式