C++: Vector3 velEmtr = new Vector3(0.0, 0.0, 0.0) compiles and runs, how?

Started by
11 comments, last by Slavik81 13 years, 9 months ago
I am working on a game with a friend and he recently checked this in:

Vector3 velEmtr = new Vector3(0.0, 0.0, 0.0);

Which to my amazement compiles and runs. I tried searching the internet for explanations but have found none. Does anyone have any insight into why this works?

I did try doing this with classes exported by libraries we are using and it did show the error I expected:

'initializing' : cannot convert from '<type> *' to '<type>'

My other question, is if that works does that memory need to be deleted?
Advertisement
Yep that looks like a memory leak combined with a strangely designed Vector3 class.

What does Vector3's definition look like? I'm guessing it has a constructor along the lines of: Vector3( const Vector3* o ) : m_x(o->m_x) ... or a similar assignment operator?

[Edit] BTW tell your friend to get away from Java/C# ;) (j/k)
Ok, yes he did just add this to the Vector3 class:

	Vector3(Vector3* initFrom)	{		x = initFrom->x;		y = initFrom->y;		z = initFrom->z;	};


So thats the problem?

Thank you very much, for some reason I didn't even consider looking in there.
Quote:Original post by KevArnold

Which to my amazement compiles and runs. I tried searching the internet for explanations but have found none. Does anyone have any insight into why this works?

- Custom operator and function overloading
- Implicit conversion
- Assignment operator, copy constructor and implicit/explicit constructor rules
- SFINAE and Koenig lookup

Big can of worms in general with lots of undefined or problematic spots.
Now sounds like a very good time to add a leak detector to your game.
Quote:Original post by KevArnold
So thats the problem?
Yes. Assuming that's supposed to be a copy constructor, the correct version would be:
Vector3(const Vector3& initFrom){   x = initFrom.x;   y = initFrom.y;   z = initFrom.z;};
Quote:Original post by Evil Steve
Quote:Original post by KevArnold
So thats the problem?
Yes. Assuming that's supposed to be a copy constructor, the correct version would be:
*** Source Snippet Removed ***


Even if it wasn't supposed to be a copy constructor thats better as it's easy to dereference a pointer on a function call, and would avoid shenanigans like this.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

Quote:Original post by KevArnold
Ok, yes he did just add this to the Vector3 class:

*** Source Snippet Removed ***

So thats the problem?

Thank you very much, for some reason I didn't even consider looking in there.


Tag that constructor with the explicit keyword. As a general rule, you should tag any constructor that takes 1 argument with 'explicit'. Your problem is similar to this:

int main(){  Vector3* myVector = new Vector3(2.0, 4.0, 3.0);  printf("myVector: %p", &myVector);  printVector(myVector);}void printVector(const Vector& aVector){   printf("aVector: %p", &aVector);}


Example Output:
myVector: 0x11111111aVector: 0x22222222


Why? Because the aVector can be implicitly constructed using a Vector3 pointer with the Vector3(Vector3*) constructor. You supplied the wrong type for the function, so it looks to see if it can implicitly construct the right type with the argument you gave it. Since there's a constructor not tagged 'explicit' that can do the job, it uses that.

Thus, your error is hidden and you can get weird and subtle bugs.

More about 'explicit': http://www.glenmccl.com/tip_023.htm
Yeah, the explicit keyword would certainly be beneficial here =)

Seemingly little-known feature of C++ as well, haven't met many folks that know about it.
It's used all the time although you mightn't notice it:

std::string s = "Hello World";

Wouldn't be possible with an explicit constructor. You'd need to use

std::string s("Hello World");

This topic is closed to new replies.

Advertisement