I'm returning to C++ after about a decade of other programming languages so bear with me here. The following program compiles for me in a C++20 project in CLion:
#include <iostream>
using namespace std;
class MyClass {
private:
public:
MyClass() {
cout << "MyClass constructor" << endl;
}
MyClass(const MyClass& myClass) {
cout << "MyClass copy constructor" << endl;
}
MyClass& operator=(const MyClass& myClass) {
cout << "MyClass operator=" << endl;
return *this;
}
friend std::ostream& operator<< (std::ostream& os, const MyClass &myClass){
return os << "MyClass stringifier";
}
~MyClass(){
cout << "MyClass destructor" << endl;
}
};
MyClass& f(){
cout << "f() entered" << endl;
MyClass x;
return x;
}
MyClass* g(){
cout << "g() entered" << endl;
MyClass x;
return &x;
}
int main() {
cout << "main() entered" << endl;
MyClass& a = f();
cout << "f() exited" << endl;
cout << a << endl;
MyClass* b= g();
cout << "g() exited" << endl;
cout << *b << endl;
}
and the output is:
main() entered
f() entered
MyClass constructor
MyClass destructor
f() exited
MyClass stringifier
g() entered
MyClass constructor
MyClass destructor
g() exited
MyClass stringifier
Now, when I hover over the return
statements, CLion does give me some warnings:
It might be interesting to note that this now quite old article mentions that the scenario generated by function f()
is "not valid" C++. Yet my compiler seems to disagree.
I am surprised that this program compiles and runs without issue. Should I not be getting a "dangling reference" error at runtime where I try to print a
and *b
? I don't think that this falls under Return Value Optimization / Copy Elision since I am not returning a new instance of MyClass
anywhere: the copy constructor is clearly not called anywhere since we can't see its printing side effect.
// Edit: The accepted answer to this SO post, posted in 2011, also seems to suggest that what f
does here should not work.