
[英]How to differentiate (when overloading) between prefix and postfix forms of operator++? (C++)
[英]How does a C++ compiler expand prefix and postfix operator++()?
考虑:
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++;
我预计它会扩展到“e.operator++(int)”之类的东西,或者更进一步,我预计
e++(2);
扩展为“e.operator++(2)”之类的东西,但我得到的是编译器抱怨一些“不匹配调用'(示例)(int)'”。
接下来我很好奇“++e”如何神秘地扩展为“e.operator++()”,即返回引用的那个。
玩了更多,我最终得到:
Example e = 1;
++e++;
e.print();
其中打印了 2,然后:
Example e = 1;
(++e)++;
e.print();
其中打印了 3。
我知道 (++e) 返回对对象的引用,然后将其后递增 1,所以这是有道理的。 我还怀疑“++e++”在这里给出了后缀运算符的优先级(正如我在另一篇文章中读到的),所以这是增加后缀运算符返回的临时变量。 这也有道理。 这让我想知道表达式是如何
++++e
++e++++
++++e++
++++e++++
被扩展(它们都以预期的结果编译和运行)。
所以真的,内部到底发生了什么,编译器如何知道要调用哪个 operator++() ,以及这些表达式是如何扩展的(尤其是在前缀情况下)? “operator++(int)”中占位符变量的用途是什么?
“operator++(int)”中占位符变量的用途是什么?
因为++
运算符有两个不同的功能:postfix-++ 和 prefix-++。 因此,在重载它时,必须有两个不同的函数签名。
编译器如何知道调用哪个 operator++(),
当您的代码使用前缀++
(例如: ++e;
)时,将调用带有签名operator++()
的函数。 当您的代码使用 postfix- ++
(例如: e++
;) 时,会调用带有签名operator++(int)
的函数,并且编译器将提供一个未指定的虚拟参数值。
从技术上讲, operator++(int)
可以使用虚拟参数值。 你可以通过编写e.operator++(5);
来传递你自己的值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
,并返回mi
为3
temp2
temp2.operator++()
- 将temp2.m_i
设置为4
并返回对temp2
的引用。 注意。 我的回答只谈到重载运算符是一个成员函数。 也可以将++
(两种形式)重载为非成员。 在这种情况下,行为将与我的描述保持一致,但“以函数调用表示法编写”表达式将采用不同的语法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.