OK, after a decade I finally have time to deal with this again.
(I'm going through some hell lately)
I took the code from Little Captain, saved it as test.cpp and tested it.
When I compile it, I get this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
user:~$ g++ -o test test.cpp
test.cpp: In function ‘int main(int, char**)’:
test.cpp:36:31: error: no matching function for call to ‘Test::Test(Test)’
Test mainObject = returnTest();
^
test.cpp:36:31: note: candidates are:
test.cpp:14:2: note: Test::Test(Test&)
Test(Test &source) {
^
test.cpp:14:2: note: no known conversion for argument 1 from ‘Test’ to ‘Test&’
test.cpp:10:2: note: Test::Test(std::string)
Test(string tag) {
^
test.cpp:10:2: note: no known conversion for argument 1 from ‘Test’ to ‘std::string {aka std::basic_string<char>}’
user:~$
|
which confirms mbozzi's prediction.
And yes, mbozzi's solution (
Test(const Test &source)
instead of
Test(Test &source)
) fixes the problem but I don't understand how and why.
The problem is, I don't understand what mbozzi means when he says:
This is because returnTest() is an rvalue which cannot bind to a non-const lvalue reference.
|
Which rvalue and which lvalue are we talking about?
I thought all l-values are supposed to be non-const.
If it's const, it cannot be an l-value.
And ANY r-value (whether const or non-const) CAN be assigned to ANY l-value.
And as far as I've read in this goddamn course I'm going through, the "const" used in front of a formal parameter only makes sure the function will not be able to modify the argument received.
That's all it supposed to do. What's that got to do with lvalues and rvalues??
As far as I CAN understand from this error message, the problem is the copy constructor expects a type "Test&" argument but instead it gets a type "Test" argument.
I'm not even sure what the damn difference is.
If I did not have anybody to advise me, I would fix this error by modifying the return type of "returnTest()".
So I changed the "returnTest()" function signature from
Test returnTest()
to
Test& returnTest()
to give the copy constructor what the hell it wants.
And when I tried to compile the error was gone, but I got instead a warning:
1 2 3 4 5 6
|
user:~$ g++ -fno-elide-constructors -o test test.cpp
test.cpp: In function ‘Test& returnTest()’:
test.cpp:28:7: warning: reference to local variable ‘myTestObject’ returned [-Wreturn-local-addr]
Test myTestObject("returnTestObject");
^
user:~$
|
And running the compiled executable gave this output in the console:
1 2 3 4 5 6 7 8 9
|
user:~$ ./test
Default Constructing
Destroying returnTestObject
Default Constructing
Destroying returnTestObject
Copying
Destroying copied
user:~$
|
And by the way, this output is the same regardles of whether I used "-fno-elide-constructors" or not ...
So now the copy constructor is only invoked when initializing "mainObject", but I'm not even sure what the hell it is initialized with, since the result of "returnTest()" is destroyed before any copy can be made to be assigned to "mainObject".
So now, to me the mess is even thicker than it was when I started this thread...
Cursed be the ***king day I was born!!