PDA

View Full Version : Some weird constructors



highnergy
22nd December 2012, 13:09
Hi,

I have came across with following constructs a lot. But I couldn't give them a meaning. Please help me understand them.





void afunction (QString& str) {...};

Suppose we have function and and gets a reference to a QString parameter. In order to call that function one has to create a QString object and pass it to the function.


QString obj("Some string");
afunction(obj);

But the weird thing is you don't have to create an object. You can just pass a string literal like "This is a Literal" to the function instead of a QString object;


afunction("This is a Literal");

and it works. Why?

Apart from sending a string literal to the above function there is also another weird way to call the function.


afunction(QString("Hello there"));

Above call works but it shouldn't. How an QString object gets created just by using class name with parantheses? It is not even creates an object. What is the meaning of QString("Hi there") alone in the function parameter list? First of all it is not the way books thought us creating objects. I can create a QString object with two ways that I know.


QString obj = new QString("Hi there"); // This creates object on the heap.
QString obj("Hello There"); // Likewise This one creates an object on the stack.

I don't know any other way to create an object. Turning back to original subject, How an object gets created just by using it's class name?


regards

amleto
22nd December 2012, 15:18
1 - that is undefined behaviour and just happens to work for you. for someone else it may crash.

2 - that is doing exactly the same as 1, believe it or not.
"QString object gets created just by using class name with parantheses?"
Yes, that is correct.

"It is not even creates an object."
Wrong, yes it does.

This is very basic c++. QString("gfds") is the QString ctor that takes a const char* (string literal) !!


"Turning back to original subject, How an object gets created just by using it's[sic] class name?"
Welcome to c++.


p.s.


QString obj = new QString("Hi there"); // This creates object on the heap. << wrong, this wont even compile
// you mean
// QString* obj = new QString("Hi there");
QString obj("Hello There"); // Likewise This one creates an object on the stack.

highnergy
22nd December 2012, 21:13
Thank you very much for your reply. After I read your post I dug a lot about subject and gathered following results.

Regarding your first answer:

1 - that is undefined behaviour and just happens to work for you. for someone else it may crash.
Actually, the reason it works is because of automatic type conversion made by compiler. const char* and const QString& are totaly different types. But when someone tries to pass a char* to QString& parameter, compiler behind the scenes tries to conver char* into a QString if it can. In order to do that it needs one thing, a QString constructor which takes a char* parameter. We all know that QString class has such a overloaded constructor. For that reason automatic type conversion successfully happens and char* gets converted into a QString.

I think the same thing happens below. I mean it should be automatic type convertion too. What do you think?

QString str = "Hello World";

Regarding your second answer:

"It is not even creates an object."
Wrong, yes it does.
Your answer is correct. QString("Blah blah") alone can create an object. In literature it is called anonymous object. It is such an object that it hasn't any variable assigned to.

wysota
22nd December 2012, 22:58
Actually, the reason it works is because of automatic type conversion made by compiler.
You should be getting a warning here as you are passing a temporary object as a non-const reference. Are you sure the function prototype is what you posted and not "const QString&"?


QString("Blah blah") alone can create an object.
Yeah, it's called a "constructor" :)

amleto
22nd December 2012, 23:34
Thank you very much for your reply. After I read your post I dug a lot about subject and gathered following results.

Regarding your first answer:

Actually, the reason it works is because of automatic type conversion made by compiler. const char* and const QString& are totaly different types. But when someone tries to pass a char* to QString& parameter, compiler behind the scenes tries to conver char* into a QString if it can. In order to do that it needs one thing, a QString constructor which takes a char* parameter. We all know that QString class has such a overloaded constructor. For that reason automatic type conversion successfully happens and char* gets converted into a QString.

I think the same thing happens below. I mean it should be automatic type convertion too. What do you think?

QString str = "Hello World";

Regarding your second answer:

Your answer is correct. QString("Blah blah") alone can create an object. In literature it is called anonymous object. It is such an object that it hasn't any variable assigned to.

first part - I already know about what you call type conversion. I already took that into consideration. The reason why I specified undefined behaviour is because you are passing an rvalue into a reference type. The reference lasts longer than the thing it is meant to be a reference of - this is undefined behaviour.

second part - more technically it is called an rvalue.


You should be getting a warning here as you are passing a temporary object as a non-const reference. Are you sure the function prototype is what you posted and not "const QString&"?

even if it's a const ref it's not valid c++ 2003 is it?. Not sure about c++11

wysota
23rd December 2012, 00:59
even if it's a const ref it's not valid c++ 2003 is it?
It is valid. That's a special case all standard compilers handle properly. I think a non-const reference to a temporary should be handled safely too however the compiler should spit out a warning about it.


Not sure about c++11
Also valid in C++11 however sometimes it can be optimized more (by using move constructors and move assignment operators).

amleto
23rd December 2012, 02:46
did some digging and I came across this:


The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object to a subobject of which the temporary is bound persists for the lifetime of the reference except as specified below. A temporary bound to a reference member in a constructor’s ctor-initializer (12.6.2) persists until the constructor exits. A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call.

highnergy
23rd December 2012, 08:52
@amleto, @wysota:

Wow, thank you very much for such a detailed explaination in a very short time.

best regards