Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Vector

This thread is locked; no one can reply to it. rss feed Print
Vector
Nakhash
Member #8,267
January 2007
avatar

Does anyone here have a sample of code they used for data in thier game which uses Vectors?

Yes, me and my Eglish teacher did not see eye to eye.

:)

Nakhash

If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com

Mark Oates
Member #1,146
March 2001
avatar

There's some really nice Vector code in Openlayer. You can download it here .

Vec2D.hpp

#SelectExpand
1#ifndef OL_VEC2D_HPP 2#define OL_VEC2D_HPP 3 4#include <cmath> 5#include <string> 6#include <sstream> 7#include "General.hpp" 8#include "Declspec.hpp" 9 10 11namespace ol { 12 13 14 15class OL_LIB_DECLSPEC Vec2D { 16public: 17 float x, y; 18 19 20 // CONSTRUCTORS // 21 22 Vec2D( float x = 0.0, float y = 0.0 ) 23 : x( x ), y( y ) {} 24 25 26 static inline Vec2D PolarCoords( float angle, float magnitude ) { 27 return Vec2D( magnitude * std::cos( angle ), magnitude * std::sin( angle )); 28 } 29 30 31 // METHODS // 32 33 inline float GetAngle() const { 34 return std::atan2( y, x ); 35 } 36 37 38 inline float GetMagnitude() const { 39 return std::sqrt( GetMagnitudeSquared() ); 40 } 41 42 43 inline float GetMagnitudeSquared() const { 44 return x * x + y * y; 45 } 46 47 48 inline Vec2D Normalized() const { 49 float magnitude = GetMagnitude(); 50 51 return Vec2D( x / magnitude, y / magnitude ); 52 } 53 54 55 // OPERATORS // 56 57 58 inline void operator += ( const Vec2D &other ) { 59 x += other.x; y += other.y; 60 } 61 62 inline void operator -= ( const Vec2D &other ) { 63 x -= other.x; y -= other.y; 64 } 65 66 67 inline void operator *= ( float factor ) { 68 x *= factor; y *= factor; 69 } 70 71 72 inline void operator /= ( float divisor ) { 73 x /= divisor; y /= divisor; 74 } 75 76 inline bool operator == ( const Vec2D &other ) const { 77 return fabs(x - other.x) < 0.01 && fabs(y - other.y) < 0.01; 78 } 79 80 inline bool operator != ( const Vec2D &other ) const { 81 return !(*this == other); 82 } 83 84 inline std::string ToString() const { 85 std::ostringstream str; 86 str << "( " << x << ", " << y << " )"; 87 return str.str(); 88 } 89 90 inline std::string GetString() const { 91 return ToString(); 92 } 93}; 94 95 96// ADDITION AND SUBTRACTION // 97 98inline Vec2D operator + ( Vec2D first, Vec2D second ) { 99 return Vec2D( first.x + second.x, first.y + second.y ); 100} 101 102 103inline Vec2D operator - ( Vec2D first, Vec2D second ) { 104 return Vec2D( first.x - second.x, first.y - second.y ); 105} 106 107 108// MULTIPLICATION AND DIVISION 109 110inline Vec2D operator * ( Vec2D vec, float factor ) { 111 return Vec2D( factor * vec.x, factor * vec.y ); 112} 113 114 115inline Vec2D operator * ( float factor, Vec2D vec ) { 116 return Vec2D( factor * vec.x, factor * vec.y ); 117} 118 119 120inline Vec2D operator / ( Vec2D vec, float divisor ) { 121 return Vec2D( vec.x / divisor, vec.y / divisor ); 122} 123 124 125// DOT PRODUCT // 126 127inline float operator * ( Vec2D first, Vec2D second ) { 128 return first.x * second.x + first.y * second.y; 129} 130 131 132// SIGN // 133 134inline Vec2D operator - ( Vec2D vec ) { 135 return Vec2D( -vec.x, -vec.y ); 136} 137 138 139// NORMALIZATION 140 141inline Vec2D operator ~ ( Vec2D vec ) { 142 return vec.Normalized(); 143} 144 145 146// TESTS 147 148 149// Checks if the points are in counter clockwise order // 150 151inline OL_LIB_DECLSPEC bool IsCounterClockwise( const Vec2D first, const Vec2D second, const Vec2D third ) { 152 float dx1, dx2, dy1, dy2; 153 154 dx1 = second.x - first.x; 155 dy1 = second.y - first.y; 156 dx2 = third.x - second.x; 157 dy2 = third.y - second.y; 158 159 return dy1*dx2 < dy2*dx1; 160} 161 162 163} 164 165 166 167 168 169 170 171 172 173 174 175#endif

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

OnlineCop
Member #7,919
October 2006
avatar

Nakhash said:

used for data in thier game

Do you mean vectors as used to draw elements, or used as a way to calculate positions...?

Or are you talking about std::vector? For that, check out either this or this site.

Nakhash
Member #8,267
January 2007
avatar

I mean like, I use Structs to contain all of my Race data for each Castle in my game. Is it possiable to use Vector to store several ints?

Nakhash

If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com

bamccaig
Member #7,536
July 2006
avatar

#SelectExpand
1#include <iostream> 2#include <vector> 3 4int main(int argc, char * argv[]) 5{ 6 std::vector<int> v; 7 8 // One way to load it with data. Check a library reference for more details. 9 v.push_back(1); 10 v.push_back(12; 11 v.push_back(23); 12 v.push_back(34); 13 v.push_back(45); 14 v.push_back(56); 15 16 std::cout << '['; 17 18 // Iterate with indexes. 19 for(int i=0, l=v.size(); i<l; i++) 20 { 21 if(i > 0) 22 std::cout << ','; 23 24 std::cout << v[i]; 25 } 26 27 std::cout << ']' << std::endl << '['; 28 29 // Iterate with iterators. 30 for(std::vector<int>::iterator it = v.begin(); it != v.end(); it++) 31 { 32 int x = (int)*it; 33 34 if(it != v.begin()) 35 std::cout << ','; // Edit: added missing semi-colon. 36 37 std::cout << x; 38 } 39 40 std::cout << ']' << std::endl; 41 42 return 0; 43}

I'm really tired (waiting for a backup process to complete) so I'm not going to test it, but if I made no mistakes it should output:

[1,12,23,34,45,56]
[1,12,23,34,45,56]

Nakhash
Member #8,267
January 2007
avatar

Your code is readable and I appreciate it. I guess what I'm asking for is, would it be possiable to use a vector like a struct..

like...

struct Character
{

 int Hitpoints;
 int Magicpoints;
 int Strength;

}GoodGuys[10];

GoodGuys[0].Hitpoints=50;
GoodGuys[0].Magicpoints=10;

and so on...
It would be nice to use a vector or something like it that could enable me to easily kill of GoodGuys[5] and still keep the data for GoodGuys[4] with GoodGuys[6] data replacing GoodGuys[5].

I have ways to code around it, but is there an easier way with STL?

Nakhash

If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com

OnlineCop
Member #7,919
October 2006
avatar

The real difference is that when you're adding items to a vector, you use push_back(), like bamccaig showed. (Note to bamccaig: Line 35 :-X)

Once you've pushed all of the numbers onto the array that you want, you can index them with the normal "[]" brackets like you do with a normal array:

  std::vector<int> array;
  array.push_back(10);
  array.push_back(-13);
  // ...
  array.push_back(6);

  int current_value = array[0]; // 0th element, value of "10"
  int next_value = array[1];    // 1st element, value of "-13"
  // ...

EDIT:

Nakhash said:

I guess what I'm asking for is, would it be possiable to use a vector like a struct..

Yes, absolutely you can do something like this. That's what the std::vector was made for. You define the "type" of vector using the "<" and ">" brackets:

#SelectExpand
1struct Character 2{ 3 4 int Hitpoints; 5 int Magicpoints; 6 int Strength; 7 8}; 9 10// ... 11 12int main() 13{ 14 // Put "Character" into the "<" and ">" brackets:
15 std::vector<Character> GoodGuys;
16 Character man1; 17 man1.Hitpoints=50; 18 man1.Magicpoints=10; 19 20 GoodGuys.push_back(man1); 21 22 Character man2; 23 man2.Hitpoints=75; 24 man2.Magicpoints=5; 25 26 GoodGuys.push_back(man2); 27 28 // ... 29 30 size_t num_GoodGuys = GoodGuys.size(); 31 for (size_t i = 0; i < num_GoodGuys; ++i) 32 { 33 // ... 34 }

Nakhash
Member #8,267
January 2007
avatar

So then with my GoodGuys code, I'd have to make a seperate Vector for every Struct element? Like

  std::vector<int> GoodGuyHitpoints;
  std::vector<int> GoodGuyMagicpoints;

  GoodGuyHitpoints.push_back(10);
  GoodGuyHitpoints.push_back(8);
  GoodGuyMagicpoints.push_back(5);

And so on...

Is there a way to group certain Vectors together like a struct, and give it a common name like I did for my struct Char?

[EDIT]

Oh my Gosh, you just changed my world... I never knew you could vector an entire struct... ::)

I'm absolutely shocked!

Nakhash

If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com

LennyLen
Member #5,313
December 2004
avatar

Nakhash said:

and so on...
It would be nice to use a vector or something like it that could enable me to easily kill of GoodGuys[5] and still keep the data for GoodGuys[4] with GoodGuys[6] data replacing GoodGuys[5].

I have ways to code around it, but is there an easier way with STL?

#SelectExpand
1struct Character 2{ 3 4 int Hitpoints; 5 int Magicpoints; 6 int Strength; 7 8} 9 10vector<Character> GoodGuys; 11 12... 13 14Character temp; 15 16// do the following for each character type you want in your Vector of Characters 17temp.Hitpoints = 50; 18temp.Magicpoints = 5; 19temp.Strength = 30; 20 21GoodGuys.push_back(temp); 22// the first one will be GoodGuys[0], then GoodGuys[1], etc, just like an array 23 24... 25 26GoodGuys.erase(GoodGuys.begin() + 4); // erases GoodGuys[5]

OnlineCop
Member #7,919
October 2006
avatar

No, no, no. Unless a single GoodGuy has multiple Hitpoints, which I don't think you want.

You want to have multiple Characters. Each Character will have its own "Hitpoints", "Magicpoints", etc. as defined in the struct that you provided earlier.

If you have "GoodGuys" defined as the vector, it's the same as having:

Character GoodGuys[3];
GoodGuys[0].Name="Bob";
GoodGuys[0].Hitpoints=50;
GoodGuys[0].Magicpoints=10;

GoodGuys[1].Name="Fredrick";
GoodGuys[1].Hitpoints=75;
GoodGuys[1].MagicPoints=5;

... and so on.

"Bob" will only have a single set of Hitpoints, value 50. "Fredrick" will have 75 Hitpoints. "Jimmy" will have his own.

What you were asking is the equivalent of "Bob" having 10 Hitpoints, as well as 8 Hitpoints, etc.

Nakhash
Member #8,267
January 2007
avatar

Yeah I saw the error of my ways after the last two responses were given...

In regards to LennyLen post, if I delete GoodGuys[5], would GoodGuys[6]'s data take it's place an so on until the entire Vector was one shorter in length?

GoodGuys.erase(GoodGuys.begin() + 4);  // erases GoodGuys[5]

[EDIT]

Vector reminds me of the push pop in Assembly Language.

Nakhash

If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com

OnlineCop
Member #7,919
October 2006
avatar

Nakhash said:

In regards to LennyLen post, if I delete GoodGuys[5], would GoodGuys[6]'s data take it's place an so on until the entire Vector was one shorter in length?

GoodGuys.erase(GoodGuys.begin() + 4); // erases GoodGuys[5]

Yes.

Therefore, if you think that you'll be deleting a lot of stuff in the middle, you may want to look into linked lists: std::list

It follows the same format as std::vector: std::list<Character>

The difference is that if you're iterating through linked lists, it takes a lot longer (because it has to start at "node 0" and iterate through each one before coming to "node 17"). With vectors, you can point right to it by simply saying "GoodGuys[17]". However, if you delete from the middle of a linked list, it unhooks the previous Node and the next Node, attaches them together, and gets rid of the one that you specified to remove.

You can get around this by a simple trick (if order doesn't matter): take the LAST element in the vector, stick it where the current element is, and then delete from the end of the vector. Then you don't have to shift all 1,000 other "Character" elements "up one".

But if order does matter, you'll just have to settle for the "shift up one" when you remove that element. ::shrug::

EDIT: Explained more. Long-winded. Yup, yup.

Nakhash
Member #8,267
January 2007
avatar

Your pretty smart for a Cop...Wolf...

I'm looking at erasing a vector each time a troop dies. So it would be about 1 every 2 mins or so. And my vector Struct will contain 8 kingdoms worth of 20-50 troops.

Vector sounds like the way to go...but I'll read about the List you are talking about. :)

Nakhash

If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com

Goalie Ca
Member #2,579
July 2002
avatar

protip:

#SelectExpand
1//use case: -(vec1 + vec2) 2//modifies and returns the unnamed vector 3//created from (vec1 + vec2) 4//requires c++0x 5Vec2D&& operator-( Vec2D&& vec ) 6{ 7 vec.x = -vec.x; 8 vec.y = -vec.y; 9 return std::move(vec); 10} 11 12//use case: -vec1 13//passes a reference rather than 14//creating and passing a copy 15Vec2D operator-( const Vec2D& vec ) 16{ 17 return Vec2D( -vec.x, -vec.y ); 18}

-------------
Bah weep granah weep nini bong!

OnlineCop
Member #7,919
October 2006
avatar

Goalie: ???
Explain that for me; I'm not used to c++0x.

Nakhash: Since you're not going to be removing them every second, std::vector sounds about right for you. The only two things you'll want to consider when doing this is:
1) If you have a LOT of elements in the array, and you remove Troops from (or near) the front of that vector, you'll have a lot of shifting to do.
2) If the order of the troops don't matter much in the overall design of the game, swapping the last element with the to-be-removed element should be considered.

I don't know how much you've worked with pointers, but I've actually found it worthwhile for me to store a vector of points to the structs/classes that I've created. Then, if you do something like "array[current_index] = array[another_index];", it won't COPY the object using the object's assignment operator ( Troop& operator= (const Troop& rhs); ). It will just copy the pointer address and you're done.

The only real overhead you have with this is that you must call new() and delete() yourself. Passing by reference, instead of passing by pointer, does all of this for you (even calling the destroyed object's destructor when appropriate), though you incur the "deep" or "shallow" copy I just mentioned.

Nakhash
Member #8,267
January 2007
avatar

OnlineCop:
1) If you have a LOT of elements in the array, and you remove Troops from (or near) the front of that vector, you'll have a lot of shifting to do.
2) If the order of the troops don't matter much in the overall design of the game, swapping the last element with the to-be-removed element should be considered.

Nakhash Reply:

I shouldn't have a lot of elements. It should be about 5 Vector structs total with the biggest one being 100 or so...

I use a lot of Structs referencing other structs which references another struct. It's like a long line of code that equals 5 or something. It enables me to not reference or make duplicates of data.

An example would be for my current game.

#SelectExpand
1 2struct ClassDef//Base Stats per Class if Unit was Level 1 3{ 4 int Strength; 5 int Defence; 6}Class[20]; 7 8struct UnitsDef //Use this for the Units Current Stats 9{ 10 int ClassID; 11 int Strength; 12 int Defence; 13 int Level; 14}Units[8][50]; 15 16struct TroopsDef 17{ 18 int UnitsID; 19 int X; 20 int Y; 21 int Faceing; 22}PlayerTroops[25];//Only Allow 25 of the total 50 Units to be in 1 battle at 1 time. 23 24 25 26Class[Units[KingdomID][PlayerTroops[TroopSelect].UnitID].ClassID].Strength

[EDIT]
Yes I've used pointers before, but I think I'll stick to the Vecter approach that was given to me. Currently I only use pointers for char that I want used in another function without declaring a global char.

Nakhash

If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com

OnlineCop
Member #7,919
October 2006
avatar

Nakhash said:

OnlineCop:
1) If you have a LOT of elements in the array, and you remove Troops from (or near) the front of that vector, you'll have a lot of shifting to do.
2) If the order of the troops don't matter much in the overall design of the game, swapping the last element with the to-be-removed element should be considered.

Nakhash Reply:

You can use <quote>...</quote> tags if it helps.

Okay...

Since your

#SelectExpand
2struct ClassDef 3{ 4 int Strength; 5 int Defense; 6};

and your

#SelectExpand
8struct UnitsDef 9{ 10 int ClassID;
11 int Strength;
12 int Defense;
13 int Level; 14};

contain two of the same variables, why not use inheritance?

struct ClassDef
{
  int Strength;
  int Defense;
};

struct UnitsDef : public ClassDef
{ int ClassID; int Level; // UnitsDef now contains Strength and Defense, as inherited from ClassDef };

Nakhash said:

I shouldn't have a lot of elements.

Quote:

#SelectExpand
1struct ClassDef 2{ 3 // ... 4}Class[20]; 5 6struct UnitsDef 7{ 8 // ... 9}Units[8][50]; 10 11struct TroopsDef 12{ 13 // ... 14}PlayerTroops[25] 15 16Class[ Units[KingdomID][PlayerTroops[TroopSelect].UnitID].ClassID ].Strength

Now, if I've broken this down correctly, you have:

  • 20 "Class" objects, each with two ints (4 bytes apiece)

  • 8*50 == 400 "Units" objects with four ints (4 bytes apiece)

  • 25 "PlayerTroops" objects with four ints (4 bytes apiece)

That's (20 * 8) * (400 * 16) * (25 * 16) bytes, or 409,600,000 :o bytes of data you're storing in memory, whether all of them are filled or not with actual data.

Yes, I'd definitely go with the vector approach, and only allocate them as needed.

Per Larsson
Member #276
April 2000
avatar

Shouldn't that be
(20 * 8) + (400 * 16) + (25 * 16) = 6960 bytes?

________________________
Guichan!

Nakhash
Member #8,267
January 2007
avatar

I don't think inheritance will work for me since I haven't fully repersented my variables in each struct. I've been going off memory to show how I'm using the data.

So in other words ClassDef has variables that UnitDef doesn't have and the Class Strength should also be a different number then the Units Strength.

I've been using ClassDef as an intro set of stats for my troops, and it also contains graphical X,Y cordance data for my sprite bitmaps that correspond to the correct Class(Job..Ex..Archer..Wizard)/Race

I do appreciate all of your guys help. :)

Nakhash

If you like Dragon Warrior, then try out my trilogy at http://dragonwarriorreborn.com

bamccaig
Member #7,536
July 2006
avatar

OnlineCop said:

Note to bamccaig: Line 35 :-X

:-X

Nakhash said:

Yes I've used pointers before, but I think I'll stick to the Vecter approach that was given to me. Currently I only use pointers for char that I want used in another function without declaring a global char.

You'd still use a std::vector, but instead of storing objects in the std::vector by value, you'd store them by pointer. It makes certain operations much faster (though complicates matters slightly by forcing you to manage memory yourself).

main.cpp#SelectExpand
1#include <iostream> 2#include <sstream> 3#include <string> 4#include <vector> 5 6class IStringifyable 7{ 8public: 9 virtual ~IStringifyable(void) = 0; 10 11 virtual std::string toString(void) const = 0; 12}; 13 14IStringifyable::~IStringifyable(void) {} 15 16class Character: 17 public IStringifyable 18{ 19 int hp_; 20 int mp_; 21 int str_; 22public: 23 Character(const int, const int, const int); 24 ~Character(void); 25 26 int getHP(void) const; 27 int getMP(void) const; 28 int getSTR(void) const; 29 30 int setHP(const int); 31 int setMP(const int); 32 int setSTR(const int); 33 34 std::string toString(void) const; 35}; 36 37Character::Character(const int hp, const int mp, const int str): 38 hp_(hp), 39 mp_(mp), 40 str_(str) 41{ 42} 43 44Character::~Character(void) {} 45 46int Character::getHP(void) const 47{ 48 return this->hp_; 49} 50 51int Character::getMP(void) const 52{ 53 return this->mp_; 54} 55 56int Character::getSTR(void) const 57{ 58 return this->str_; 59} 60 61int Character::setHP(const int hp) 62{ 63 return this->hp_ = hp; 64} 65 66int Character::setMP(const int mp) 67{ 68 return this->mp_ = mp; 69} 70 71int Character::setSTR(const int str) 72{ 73 return this->str_ = str; 74} 75 76std::string Character::toString(void) const 77{ 78 std::stringstream ss; 79 80 ss << "{\n" 81 << " HP : " << this->hp_ << ",\n" 82 << " MP : " << this->mp_ << ",\n" 83 << " STR : " << this->str_ << "\n" 84 << "}"; 85 86 return ss.str(); 87} 88 89std::ostream & operator<<(std::ostream & out, const IStringifyable & strable) 90{ 91 return out << strable.toString(); 92} 93 94typedef std::vector<Character *> CharacterPtrVector; 95 96int main(int argc, char * argv[]) 97{ 98 CharacterPtrVector v; 99 100 v.push_back(new Character(100, 100, 23)); 101 v.push_back(new Character(87, 121, 15)); 102 v.push_back(new Character(53, 534, 22)); 103 v.push_back(new Character(234, 32, 51)); 104 105 for(int i=0, l=v.size(); i<l; i++) 106 { 107 const Character * const chr_ptr = v[i]; 108 109 // Output our characters, one by one. 110 std::cout << *chr_ptr << std::endl << std::endl; 111 112 // We might as well use the same loop for cleanup. 113 delete chr_ptr; 114 } 115 116 /* 117 * We've already deleted all of the objects so we should clear the vector to 118 * release the pointers. 119 */ 120 v.clear(); 121 122 return 0; 123}

$ g++ -c main.cpp
$ g++ -o chrvct main.o
$ ./chrvct
{
    HP : 100,
    MP : 100,
    STR : 23
}

{
    HP : 87,
    MP : 121,
    STR : 15
}

{
    HP : 53,
    MP : 534,
    STR : 22
}

{
    HP : 234,
    MP : 32,
    STR : 51
}

$ 

The advantage to using pointers is that container operations won't cause copies of entire objects. Only their memory addresses need to be copied. Even better, if you don't mind installing Boost, would be using boost::shared_ptr<Character> (or if you've got a C++0x compatible compiler, std::shared_ptr<Character>) because it acts just like a pointer and is efficient like a pointer, but cleanup is automatic[1].

References

  1. There are certain gotchas to look out for, like circular references between shared pointers, but it's pretty easy to avoid problems.
Goalie Ca
Member #2,579
July 2002
avatar

OnlineCop said:

Goalie:
Explain that for me; I'm not used to c++0x.

Okay I will.. someone please bookmark/remind me to make a wiki if this ends up being referred to in other posts.

//use case: -(vec1 + vec2)
//modifies and returns the unnamed vector 
//created from (vec1 + vec2)
//requires c++0x
Vec2D&& operator-( Vec2D&& vec )
{
  vec.x = -vec.x;
  vec.y = -vec.y;
  return std::move(vec);
}

So, in C++ there are r-values and l-values. An r-value is a value without an explicit name.. these are temporary objects that can only be accessed in one way.

Vec2D a(1,2);
Vec2D b(-1,2);

Vec2D c = (a + b) - b;

In this example a,b,c are named variables. That means that any line of code in that scope can use the label (ie: name) to access that object.

(a+b) is a function of named variables a and b and returns a variable. What is this variable called? It is unnamed therefore nowhere else in the code can touch that result. This means that we can make an optimization here! Let us re-use the result from (a+b) by storing the result of (a+b)-b into the temporary created by (a+b).

Vec2D&& operator-(Vec2D&& ab, const Vec2D& b)
{
   ab.x -= b.x;
   ab.y -= b.y;
   return std::move(ab);
}

So && is the C++0x notation for r-value. Once we give an r-value a name it becomes an l-value. So ab is an l-value. But we want to return an r-value here so we use std::move which simply casts an l-value to an r-value. Notice how we re-use the temporary ab rather than making a new-copy!

-------------
Bah weep granah weep nini bong!

anonymous
Member #8025
November 2006

Except why would that be any optimization here if there's nothing to be gained from moving?

With the following the version with rvalue references appears to be slower.

#SelectExpand
1#include <iostream> 2#include <ctime> 3 4#define USE_RVALUE_MINUS 1 5struct Vec2D 6{ 7 int x, y; 8}; 9 10Vec2D operator+(const Vec2D& a, const Vec2D& b) 11{ 12 return { a.x + b.x, a.y + b.y }; 13} 14 15#if USE_RVALUE_MINUS 16Vec2D&& operator-( Vec2D&& vec ) 17{ 18 vec.x = -vec.x; 19 vec.y = -vec.y; 20 return std::move(vec); 21} 22#else 23 24Vec2D operator-(const Vec2D& vec) 25{ 26 return {-vec.x, -vec.y }; 27} 28#endif 29 30int main() 31{ 32 clock_t start = clock(); 33 Vec2D a{1, 2}, b{1, -1}; 34 for (int i = 0; i != 10000000; ++i) { 35 a = -(a + b); 36 } 37 std::cout << clock() - start << ' ' << a.x << ' ' << a.y; 38}

Goalie Ca
Member #2,579
July 2002
avatar

anonymous said:

Except why would that be any optimization here if there's nothing to be gained from moving?

std::move does nothing but cast from Var& to Var&&. Where is the code that runs the actual test?

Say for example you had a string..

string&& operator+( string&& a, const string& b )
{
 //some magic
}

//write out other permutations of arguments...

string& operator+( const string& a, const string& b)
{
 //some different magic
}

Then you would see a great performance increase from something like this

string c = a + b + "hello world " + d + e + f + g + "something else ";

In many programming languages they say avoid doing this because it constructs a new string for every addition and then throws it away. A lot of language tell you to use a.join etc. With r-values you can mimic that join behavior with a naive syntax.

-------------
Bah weep granah weep nini bong!

anonymous
Member #8025
November 2006

String's a different thing indeed. But with something as simple as a Vec2D, everything goes on on the stack, and the compiler, I assume, can optimize away the temporaries via return value optimizations and inlining.

I have feeling there isn't much point to bother exploding the number of overloads you need for simple things like that.

Go to: