请考虑:
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)”这样的内容,但实际上编译器却抱怨一些“no match for call to '(Example) (int)'”。
接下来,我好奇“++e”是如何神奇地转换为返回引用的“e.operator++()”方法的。
继续尝试,最终得到:
Example e = 1;
++e++;
e.print();
打印出了2,然后:
Example e = 1;
(++e)++;
e.print();
打印3。
我理解(++e)返回对对象的引用,然后将其后置递增一次,所以这是有道理的。我还怀疑“++e++”在这里给出了后缀运算符的优先级(正如我在另一个帖子中所读到的),因此这会递增后缀运算符返回的临时变量。这也是有道理的。这使我想到了像下面这样的表达式:
++++e
++e++++
++++e++
++++e++++
这些代码都被扩展了(它们都可以编译并得到预期的结果)。
那么,实际上内部发生了什么,编译器如何知道调用哪个operator++(),这些表达式如何扩展(特别是在前缀情况下)?"operator++(int)"中占位符变量的目的是什么?
Example operator++(int) { return Example(m_i++); }
- Christopher Oicles