Jump to content

  • Log In with Google      Sign In   
  • Create Account


sizeof() giving strange results...


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
28 replies to this topic

#1 Tasche   Members   -  Reputation: 222

Like
0Likes
Like

Posted 22 January 2013 - 09:33 AM

i wrote a 3d vector class a while ago, been using it ever since without problem, now recently i found out it seems to have the wrong size in bytes
class Vector3 {
public:
    float x;
    float y;
    float z;
    Vector3();
    Vector3(const Vector3 &v);
    Vector3(float xIn, float yIn, float zIn);
    virtual Vector3 operator=(const Vector3 &rhs);
     ...
};
this yields a sizeof() of 16 bytes instead of 12.
by trying around, i found out that it is due to the the operator(s) being virtual (or any virtual method i add, even the destructor)
if i leave out the 'virtual' keyword, the size is correct, but the linker cant resolve the symbols.

any idea how to handle this, or why the use of 'virtual' changes a classes size?

also, pls dont link descriptions to the virtual keyword, i have been through many, and still don't get it =)
thanks in advance,
Tasche

Edited by rip-off, 22 January 2013 - 05:08 PM.


Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9500

Like
8Likes
Like

Posted 22 January 2013 - 09:54 AM

The class gets bigger because of a pointer to the vtable. That said, there shouldn't be any reason that a vector class should have any virtual functions in it. Inheriting from a 3D vector is a somewhat bizarre option.

#3 Servant of the Lord   Crossbones+   -  Reputation: 18279

Like
5Likes
Like

Posted 22 January 2013 - 01:02 PM

Virtual is for inheritance purposes - your class isn't inheriting, and likely shouldn't be inherited from, so none of the functions should be virtual.

 

operator= is supposed to return a reference: "Vector3 &operator=(const Vector3 &rhs);"

 

What does your function declaration look like? Your linker errors may be related to that. Could you post the error message?


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                            [Need web hosting? I personally like A Small Orange]
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#4 Álvaro   Crossbones+   -  Reputation: 12509

Like
3Likes
Like

Posted 22 January 2013 - 02:03 PM

Also, if you don't provide a copy constructor or an operator=, the compiler will make some for you that will work just fine.

#5 Zao   Members   -  Reputation: 878

Like
0Likes
Like

Posted 22 January 2013 - 02:29 PM

operator= is supposed to return a reference: "Vector3 &operator=(const Vector3 &rhs);"

 

This is just convention, nowhere does the standard mandate that an copy assignment operator shall have any particular return type, it could even return void. The only requirement is that it shall have exactly one parameter as per C++11 13.5.3/1. 13.5.3/2 has an example with an copy assignment operator returning an int by value, for example.

 

As Álvaro mentions, if you do not declare a copy assignment operator, one will be implicitly declared and synthesised for you that does an element-wise assignment of the members.


To make it is hell. To fail is divine.

#6 Álvaro   Crossbones+   -  Reputation: 12509

Like
3Likes
Like

Posted 22 January 2013 - 02:39 PM

This is just convention [...]
Conventions are important. The standard lets you have an operator + that modifies its operands, overload operator comma (,) and many other horrible things that will confuse the hell out of anybody reading your code. Trying to minimize surprises for anyone reading your code is a very good thing to do, and returning a reference from operator= goes well with that philosophy.

Edited by Álvaro, 22 January 2013 - 02:40 PM.


#7 ApochPiQ   Moderators   -  Reputation: 14673

Like
4Likes
Like

Posted 22 January 2013 - 02:59 PM

Truth. Just because you can, doesn't mean you should.

Returning a mutable reference allows lots of nice things, such as chained assignments, and shorthand such as:
(flatVector = vector3d).z = 0.0f;


#8 Washu   Senior Moderators   -  Reputation: 4698

Like
5Likes
Like

Posted 22 January 2013 - 03:00 PM

Truth. Just because you can, doesn't mean you should.

Returning a mutable reference allows lots of nice things, such as chained assignments, and shorthand such as:
(flatVector = vector3d).z = 0.0f;
 



I would fire you for that code.

Then I would set you on fire for that code.

Then I would launch a whole army of bots against you to burn those remaining bits of you that were left for that code.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX


#9 Bregma   Crossbones+   -  Reputation: 4852

Like
0Likes
Like

Posted 22 January 2013 - 03:22 PM


operator= is supposed to return a reference: "Vector3 &operator=(const Vector3 &rhs);"

 
This is just convention, nowhere does the standard mandate that an copy assignment operator shall have any particular return type, it could even return void. The only requirement is that it shall have exactly one parameter as per C++11 13.5.3/1. 13.5.3/2 has an example with an copy assignment operator returning an int by value, for example.
 


Well, if you think about it, it doesn't make a lot of sense to have a copy operator return a copy rather than a reference. Sure, you could return an int, or a pointer, or even nothing at all (void). But to return a copy, you would need to invoke the copy operator, which invokes the copy operator, which... well, maybe you get my point.

I imagine the OP's problem is that the compiler can't find the definition for the copy assignment operator during the definition of the copy assignment operator, because it hasn't been defined yet. I think SotL's answer is the best so far.
Stephen M. Webb
Professional Free Software Developer

#10 SiCrane   Moderators   -  Reputation: 9500

Like
2Likes
Like

Posted 22 January 2013 - 03:28 PM

But to return a copy, you would need to invoke the copy operator, which invokes the copy operator, which... well, maybe you get my point.
Different copy mechanism. Returning by copy would invoke the copy constructor, not the assignment operator.

#11 Servant of the Lord   Crossbones+   -  Reputation: 18279

Like
2Likes
Like

Posted 22 January 2013 - 04:04 PM

operator= is supposed to return a reference: "Vector3 &operator=(const Vector3 &rhs);"

 
This is just convention, nowhere does the standard mandate that an copy assignment operator shall have any particular return type, it could even return void.


Good point, but if the OP followed convention in his declaration, and didn't in his definition, he'd get an error which he might've mistaken for a linker error.

 

class Test
{
	public:
	//Return by value.
	Test operator=(const Test &other);
};

//Return by reference.
Test &Test::operator=(const Test &other)
{
	return *this;
}

int main()
{
	Test testA, testB;
	testA = testB;

	return 0;
}


prototype for 'Test& Test::operator=(const Test&)' does not match any in class 'Test'
candidate is: Test Test::operator=(const Test&)


Forgetting (or mistakenly adding) a single character is a rather easy mistake to make. ph34r.png

 

A similar result would occur if he took the parameter by reference or value instead of const-reference, and didn't do so uniformly. Until he gives his actual code (for the entire class definition and declaration), and posts what errors he got, we can't know for sure.

 


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                            [Need web hosting? I personally like A Small Orange]
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#12 ApochPiQ   Moderators   -  Reputation: 14673

Like
3Likes
Like

Posted 22 January 2013 - 04:21 PM

I would fire you for that code.

Then I would set you on fire for that code.

Then I would launch a whole army of bots against you to burn those remaining bits of you that were left for that code.


Like I said... just because you can... :-D

#13 Tasche   Members   -  Reputation: 222

Like
0Likes
Like

Posted 22 January 2013 - 04:34 PM

The class gets bigger because of a pointer to the vtable.

ok this is exactly what i wanted to hear, even if it doesnt solve my problem.

 

 

That said, there shouldn't be any reason that a vector class should have any virtual functions in it. Inheriting from a 3D vector is a somewhat bizarre option.

 

Virtual is for inheritance purposes - your class isn't inheriting, and likely shouldn't be inherited from, so none of the functions should be virtual.

yeah i know, and i don't want to do that. i usually only use virtual functions to create 'interface classes' which have several context specific implementations, and the one used gets decided at runtime. this at least is what i've been using virtual for, to exploit polymorphism

the way i used them here, to be honest, i just discovered by mistake that they worked, i have no idea as to why one would need the 'virtual', and what it does. like i said, the linker bugs me if i don't, if i do, everything works 100% as expected, except the vtable pointer gets added (which i cant have due to memory alignment issues). even more important, i want to know why the one version with virtual works, while the other raises linker errors, even though there's no inheriting going on whatsoever, since this code is being written for educational purposes.

What does your function declaration look like? Your linker errors may be related to that. Could you post the error message?

hm... this is the declaration. are you maybe referring to the definition?

inline Vector3 Vector3::operator=(const Vector3 &v)
{
	Vector3 ret;
	ret.x = x = v.x;
	ret.y = y = v.y; 
	ret.z = z = v.z;
	return ret;
}

the linker error i get when NOT using virtual:

error LNK2001: Uresolved external Symbol ""public: class Vector3 __thiscall Vector3::operator=(class Vector3 const &)" (??4Vector3@@QAE?AV0@ABV0@@Z)".

ok, thanks sofar for all those answers, im sort of a newb here, and really appreciate this. also thanks for not posting workarounds or alternatives, since that wont help me (read the bold text again to find out why =) ).

 

needless to say, i got more ops overloaded, which aren't assignments they suffer the same dilemma

 

thanks again, can't wait to get on this again

 

cheers,

    tasche



#14 Paradigm Shifter   Crossbones+   -  Reputation: 5235

Like
1Likes
Like

Posted 22 January 2013 - 04:39 PM

The compiler is probably getting confused if you inline it and it isn't available to all translation units (i.e. you need to define it in the class declaration or in the header)?
"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

#15 Tasche   Members   -  Reputation: 222

Like
0Likes
Like

Posted 22 January 2013 - 04:55 PM

The compiler is probably getting confused if you inline it and it isn't available to all translation units (i.e. you need to define it in the class declaration or in the header)?

haha yes that solved it... stupid me for not seeing it myself
i just removed the 'inline' keyword. took me some time googling to fully understand whats going on, but i get it now smile.png

this can be closed i guess

thanks a plenty to everyone again, <3 this forum

EDIT: i also moved to returning a reference for assignments:

Vector3 &Vector3::operator=(const Vector3 &v)
{
	x = v.x;
	y = v.y; 
	z = v.z;
	return *this;
}

i assume this the proper way to do this?



#16 EWClay   Members   -  Reputation: 659

Like
0Likes
Like

Posted 22 January 2013 - 05:03 PM

That explains it. If the function is virtual the compiler must include it even though it is marked inline, since it needs a pointer to the function for the virtual function table. If it's not virtual it will skip it, since it assumes that the definition will always be available. And if the definition is not available somewhere ... linker error.

#17 rip-off   Moderators   -  Reputation: 8070

Like
1Likes
Like

Posted 22 January 2013 - 05:09 PM

Please do not mark threads as "solved".



#18 Tasche   Members   -  Reputation: 222

Like
0Likes
Like

Posted 22 January 2013 - 05:12 PM

That explains it. If the function is virtual the compiler must include it even though it is marked inline, since it needs a pointer to the function for the virtual function table. If it's not virtual it will skip it, since it assumes that the definition will always be available. And if the definition is not available somewhere ... linker error.

yep, this is exactly what i gathered after searching around, the virtual keyword forcing to include it for the v. table, and the linker therefore not fussing about it missing =)



#19 Tasche   Members   -  Reputation: 222

Like
0Likes
Like

Posted 22 January 2013 - 05:14 PM

Please do not mark threads as "solved".

hm, yeah, sorry must have missed that bit in the rules...



#20 pinebanana   Members   -  Reputation: 475

Like
0Likes
Like

Posted 23 January 2013 - 12:54 AM

The compiler is probably getting confused if you inline it and it isn't available to all translation units (i.e. you need to define it in the class declaration or in the header)?

haha yes that solved it... stupid me for not seeing it myself
i just removed the 'inline' keyword. took me some time googling to fully understand whats going on, but i get it now smile.png

this can be closed i guess

thanks a plenty to everyone again, <3 this forum

 

 

EDIT: i also moved to returning a reference for assignments:

Vector3 &Vector3::operator=(const Vector3 &v)
{
	x = v.x;
	y = v.y; 
	z = v.z;
	return *this;
}

i assume this the proper way to do this?

Shouldn't it be:

 

 

Vector3& Vector3::operator=(const Vector3& v)
{
       if(this != &v)
       {
             x = v.x;
             y = v.y;
             z = v.z;
       }
       
       return *this;
}

 

Oh and why not use a pre-made math library such as GLM?


Edited by pinebanana, 23 January 2013 - 12:56 AM.

anax - An open source C++ entity system





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS