考虑:
class Example
{
private:
int m_i;
public:
Example(int i) : m_i{i} {}
//Post-fix
Example operator++(int) {m_i++; return *this;}
//Pre-fix
Example& operator++() {m_i++; return *this;}
void print() const {std::cout << m_i << '\n'}
};
我正在试验这个以确定编译器如何扩展对前缀和后缀运算符的调用。
例如,当我写这样的东西时:
Example e = 1;
e++;
我希望它扩展到类似&#34; e.operator ++(int)&#34;,或者更进一步,我期待
e++(2);
扩展为类似&#34; e.operator ++(2)。&#34;,但我得到的是编译器抱怨某些&#34;不匹配调用&#39;(示例)(int)&#39;&#34;。
接下来我很好奇&#34; ++ e&#34;神秘地扩展为&#34; e.operator ++()&#34;,即返回引用的那个。
再玩一些,我最终得到了:
Example e = 1;
++e++;
e.print();
哪个打印2,然后:
Example e = 1;
(++e)++;
e.print();
打印3。
我理解(++ e)返回对象的引用,然后将其递增1,所以这是有道理的。我也怀疑&#34; ++ e ++&#34;在这里给出后缀运算符优先级(正如我在另一篇文章中读到的那样),所以这是递增后缀运算符返回的临时变量。这也是有道理的。这让我想知道像
这样的表达方式++++e
++e++++
++++e++
++++e++++
被扩展(它们都编译并运行预期结果)。
真的,内部到底发生了什么,编译器如何知道调用哪个运算符++(),以及如何扩展这些表达式(特别是在前缀的情况下)?占位符变量在&#34; operator ++(int)&#34;?
中的用途是什么答案 0 :(得分:2)
“operator ++(int)”中占位符变量的用途是什么?
因为++
运算符有两个不同的函数:postfix - ++和prefix - ++。因此,当重载它时,必须有两个不同的功能签名。
编译器如何知道调用哪个运算符++(),
当您的代码使用前缀 - ++
(例如:++e;
)时,将调用带有签名operator++()
的函数。当您的代码使用postfix - ++
(例如:e++
;)时,将调用带有签名operator++(int)
的函数,编译器将提供未指定的伪参数值。
从技术上讲,operator++(int)
的实现可以使用伪参数值。您可以通过编写e.operator++(5);
而不是e++;
来传递自己的价值。但这会被认为是错误的编码风格 - 当重载运算符时,建议保留内置运算符的语义,以避免混淆读取代码的人。
请注意,您当前的postfix实现 - ++
不遵守此规则:正常的语义是应该返回前一个值;但是你的代码会返回更新后的值。
++e++++;
要解析此语句,您需要了解这些解析规则:
++ e ++ ++;
(而不是一些一元 - +
运算符)。咨询该表达式的表格会告诉您:++(((e++)++))
。使用前面提到的扩展,可以用函数调用表示法编写:
((e.operator++(0)).operator++(0)).operator++();
在这种情况下,需要从左到右调用这些函数,因为在调用它的表达式之前无法输入成员函数。
因此,假设我们在此语句之前有Example e(1);
,则按以下顺序发生以下函数调用:
e.operator++(int)
- 将e.m_i
设置为2
并返回一个临时(我将其称为temp1
作为伪代码)temp1.m_i
为2
}。temp1.operator++(int)
- 将temp1.m_i
设置为3
,并返回temp2
为m.i
3
temp2.operator++()
- 将temp2.m_i
设置为4
并返回对temp2
的引用。 NB。我的回答只谈到重载运算符是一个成员函数。也可以将++
(两种形式)作为非成员重载。在这种情况下,行为将不会改变我的描述,但“写入函数调用符号”表达式将采用不同的语法。