• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Tasche

sizeof() giving strange results...

28 posts in this topic

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
0

Share this post


Link to post
Share on other sites
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.

0

Share this post


Link to post
Share on other sites

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.
0

Share this post


Link to post
Share on other sites
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.
2

Share this post


Link to post
Share on other sites

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.

 

2

Share this post


Link to post
Share on other sites
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

0

Share this post


Link to post
Share on other sites
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)?
1

Share this post


Link to post
Share on other sites
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?

0

Share this post


Link to post
Share on other sites
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.
0

Share this post


Link to post
Share on other sites
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 =)

0

Share this post


Link to post
Share on other sites
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
0

Share this post


Link to post
Share on other sites

[quote name='pinebanana' timestamp='1358924066' post='5024617']
Shouldn't it be:
[/quote]
It's rather trivial in this case; nothing will be harmed by assigning three floats to themselves. Past attempting to maintain the invariants of the class, there is little other reason to check to see if you are assigning to yourself for a class that contains nothing but primitive types.

http://www.parashift.com/c++-faq/self-assignment-how.html

 

If you don't need to explicitly test for self-assignment, for example, if your code works correctly (even if slowly) in the case of self-assignment, then do not put an if test in your assignment operator just to make the self-assignment case fast. The reason is simple: self-assignment is almost always rare, so it merely needs to be correct - it does not need to be efficient. Adding the unnecessary if statement would make a rare case faster by adding an extra conditional-branch to the normal case, punishing the many to benefit the few.

In other words, don't stick one in just to do it. Do it for a provable reason that isn't speed.

1

Share this post


Link to post
Share on other sites

Shouldn't it be:


It's rather trivial in this case; nothing will be harmed by assigning three floats to themselves. Past attempting to maintain the invariants of the class, there is little other reason to check to see if you are assigning to yourself for a class that contains nothing but primitive types.

http://www.parashift.com/c++-faq/self-assignment-how.html

 

 

If you don't need to explicitly test for self-assignment, for example, if your code works correctly (even if slowly) in the case of self-assignment, then do not put an if test in your assignment operator just to make the self-assignment case fast. The reason is simple: self-assignment is almost always rare, so it merely needs to be correct - it does not need to be efficient. Adding the unnecessary if statement would make a rare case faster by adding an extra conditional-branch to the normal case, punishing the many to benefit the few.

In other words, don't stick one in just to do it. Do it for a provable reason that isn't speed.

 

Ah, my bad.

1

Share this post


Link to post
Share on other sites

[quote name='pinebanana' timestamp='1358929687' post='5024636']
Ah, my bad.
[/quote]
No harm done.

0

Share this post


Link to post
Share on other sites
No, it shouldn't be. Self assignment is harmless in this case and it's quicker not to do the branch.
0

Share this post


Link to post
Share on other sites

Btw, since equality operator in a Vector3 class is highly likely to be used frequently, you should seriously consider inlining it back. Just make sure it's available all translation units. You can define it in the header, or to make the code more tidy and clean, define it in an "inl" file and include it in the Vector3 header.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0