Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CPP Reference in Constructor and Function

Am bit confused on the below code. `

class sample
{
     public:
     sample() {  }
     sample( sample& Obj ) {  }
 };

void fun( sample& Obj ) {   }

int main()
{
    sample s(sample());
    fun( sample() );
    return 0;
}

am getting the below error

Compilation failed due to following error(s). main.cpp: In function 'int main()': main.cpp:29:19: error: invalid initialization of non-const reference of type 'sample&' from an rvalue of type 'sample' fun( sample() );

I understood changing the argument in fun from sample& obj to const sample &obj will resolve the error.

My Question is, Even for copy constructor also, a temporary object has been send. But why compiler didn't throw the same error.

Nice explanation are most welcome

Regards Prasath S.

like image 905
Prasath Shanmugakani Avatar asked Jan 02 '23 18:01

Prasath Shanmugakani


2 Answers

This line:

sample s(sample());

Is a declaration of a function called s that returns a sample object and takes as argument a function taking no arguments and returns a sample object. You're not calling the copy constructor at all. It's called "most vexing parse". Though some people object to that name.

You can see this is the case by writing to the console or putting a break point in the copy constructor, it will never be called. Another thing you will see is by adding a variable member to your class and trying to access it won't work. After the line:

sample s(sample());

Try to use:

s.sampleMember = 1;

And it will fail to compile on the grounds that s is a function declaration and not an object. There are a couple of ways to avoid this, you can surround the argument in another set of brackets:

sample s((sample()));

Or you can use C++11 onward style brace initialisation with something like:

sample s(sample{});
like image 137
Zebrafish Avatar answered Jan 05 '23 16:01

Zebrafish


There are 2 problems here:

The one is "most vexing parse" problem in the line:

sample s(sample());

, like already mentioned. You are declaring function taking function with no argument as parameter and returning sample as value. Putting braces like sample s((sample())) or using new c++11 syntax sample s(sample{}) solves this problem.

The other one is that non-const lvalue reference cannot be bound to an rvalue, what your intent probably was in the line:

fun( sample() );

You have to declare fun argument to:

void fun( const sample& Obj ) {   }

or (since c++11)

 void fun( sample&& Obj ) {   }

(assumed you dont want to change Obj within fun) then only const lvalue references or rvalue references can bind to rvalues. Otherwise if your intent is to change Obj within fun you have to leave the declaration non-const lvalue reference:

void fun(sample& Obj ) {   }

and call it with some lvalue, like

fun(s)
like image 32
StPiere Avatar answered Jan 05 '23 17:01

StPiere