• Advertisement
Sign in to follow this  

If you ever used a vector in c++ could you show...

This topic is 1226 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Advertisement

If you're talking about std::vector, then the equivalent is asking what is the use for a closet. You can store lots of things in a closet. Be it clothes, shoes, money, documents. If documents, they can be in alphabetical order, in chronological order, in random order. There's almost no limit.

 

Vector is the most generic container.

It's the equivalent of a pointer array in C, except you get a few bonuses (don't have to worry about deallocation most of the time, the array can be resized automatically)

Share this post


Link to post
Share on other sites

It's the equivalent of a pointer array in C

 

Calling it that could make people incorrectly assume it's literally an array of pointers, when you refer to the equivalent of

ElementType* v = (ElementType*)calloc(n, sizeof(ElementType)); (minus all the tedious fiddling with resizing, freeing, etc.)

 

The only thing not to do with a vector is to keep pointers to the elements, unless you are absolutely sure that your vector is done growing.

Share this post


Link to post
Share on other sites

I have dozens of possible examples; what are you hoping to learn?

Dozens?? Try hundreds if not thousands. Nearly everything in our codebase is driven by vectors. If I have one of something, it lives in a variable/object. If I have two or more of something, it goes into a vector. We literally never use operator new[] or delete[].

Edited by Promit

Share this post


Link to post
Share on other sites

i had a rigorous background in simpler programming venues that gravitated me towards retaining simple methods.

the reason to use vectors is because they are simpler, eg. if you have two 3d points stored as vectors, you can add them by writing a + b instead of separately adding each dimension. makes code easier to read and write :)
 

Share this post


Link to post
Share on other sites

i had a rigorous background in simpler programming venues that gravitated me towards retaining simple methods.

the reason to use vectors is because they are simpler, eg. if you have two 3d points stored as vectors, you can add them by writing a + b instead of separately adding each dimension. makes code easier to read and write smile.png
 

That's a different kind of vector.

LAURENT* could be talking about that kind of vector (math related), or he could be talking about the container type std::vector.

That is:

Vector myVector = {0.0f, 15.3f, -27.0f};

vs

std::vector<int> myVector;

 

Both types of vectors are used constantly.

Share this post


Link to post
Share on other sites

If you were writing code for a toaster with 1000 bread slots, you could use "std::vector<bool> slotsWithBread;" to keep track of which slots have bread in them. :)

Share this post


Link to post
Share on other sites

Show me what you were doing with this and possibly explain why?

(paraphrased for brevity)

#include <string>

#include <vector>

 

void mymethod()

{

   std::vector<std::string> labels;

 

   labels.push_back("up");

   labels.push_back("down");

   labels.push_back("left");

   labels.push_back("right");

 

   std::vector<std::string>::iterator it = labels.begin();

   for(; it < labels.end(); ++it)

      std::cout << *itr->c_str() << std::endl;

}

 

vectors are (arguably) the simplest container class in the STL. THAT's why they are used often. Their simplicity make them generally applicable to many types of problems. Think of a vector as a stack of single slot shelves, shelves that can store ANY object; but with the caveat that once you decide what object you want to store in them THAT'S the only kind of object you can place in them. Vectors are different from stacks as you can access any element at any position in the stack (random access).

Edited by xeyedmary

Share this post


Link to post
Share on other sites

If you could post examples you feel would help me best understand how vectors work, that would be helpful. Vectors seems to be something very helpful use so I thought I might get the best understanding of it by seeing how their used by you guys at GDevs. I might have a few questions.

Share this post


Link to post
Share on other sites
I think you're going at this backwards.

Pneumatic hammers are very useful, but I don't think the best way to learn how to use them is to watch YouTube videos of dudes breaking up concrete.

You might be better served picking a problem and then asking how vectors might play into the solution.



Just my opinion, though.

Share this post


Link to post
Share on other sites

If you could post examples you feel would help me best understand how vectors work, that would be helpful. Vectors seems to be something very helpful use so I thought I might get the best understanding of it by seeing how their used by you guys at GDevs. I might have a few questions.

 

Have you used dynamic arrays before? Like this:

int* pIntegers = new int[100];
for(int i = 0; i < 100; i++)
{
    pIntegers[i] = i;
}

for(int i = 0; i < 100; i++)
{
    std::cout << pIntegers[i];
}
delete[] pIntegers;

std::vector is pretty much the same thing - just much safer (i.e. no memory-leaks), and with some additional out-of-the-box-functionality. You can (and possibly should) use them wherever you have been using plain "new type[count]" and so on until now:

std::vector<int> vIntegers;
vIntegers.reserve(100); // we know the amount of values beforehands, so we can tell this the vector to safe performance
for(int i = 0; i < 100; i++)
{
    vIntegers.push_back(i); // inserts i as the last element
}

for(auto integer : vIntegers) // c++11 range based for-loop, "integer" holds the current value in the vector
{
    std::cout << integer;
}

This code works identical to the first one. There is a few specialities to vectors which you can see here - like the way you can iterate them, "reserving" the memory before inserting a known amount of values, etc... but you'll learn them as you go.

 

Just a few (negativ-ish) things to keep in mind when using vectors:

 

- They can greatly reduce performance in debug-mode, when iterator debuggin is turned on and when you are iterating over them in a loop. Performance in "release" in Visual studio and likewise is identical to a plain array, so no need to worry here - just don't feel confused when you suddenly see a decrease in performance while debugging when changing from pointers/arrays to vector.

 

- As they are templates, they can slow down compile-time and increase EXE size. This does not happen in a huge extent anymore, and is not a huge problem anymore today - though using precompiled header files and using extern template declaration might help, if you are experiencing any of those problems (and have access to c++11 for the extern thingy).

 

Hope that helps.

Edited by Juliean

Share this post


Link to post
Share on other sites

I think you're going at this backwards.

 

Pneumatic hammers are very useful, but I don't think the best way to learn how to use them is to watch YouTube videos of dudes breaking up concrete.

 

You might be better served picking a problem and then asking how vectors might play into the solution.

 

Have to disagree. If you don't know what a pneumatic hammer is, and you've never seen one in use, watching YouTube is probably a very useful place to start.

 

SeanMiddleditch: std::vectors are "dynamically-resizable contiguously-allocated containers of data." N.B., will resize itself automatically, and store the contents in one block of memory.

 

As an example where automatic resizing and contiguous allocation are useful:

 

You want to create a vertex buffer of some yet-to-be-determined number of vertices. E.g., you're reading vertex positions from a file and don't know exactly how many of them there are. Further, when the vertices have been read into your application, you want to create a vertex buffer with the new data.

 

Using pseudo-code:

 

First step: define a structure to hold the vertex data read in. Make the structure reflect how the data is to appear in the vertex buffer.

struct MyVertex
{
   Vector3 pos;
};

Step two: create a std::vector that can hold a large number of those vertex structures.

std::vector<MyVertex> vertices; // the vector is empty at this point, but expects MyVertex structures to be pushed into it

Step three: read in data, stuffing each vertex into a MyVertex structure and add it to vertices.

while( not end-of-file )
{
   MyVertex aVertex;
   float posx, posy, posz;
   file >> posx >> posy >> posz; // read data from a file in some way
   aVertex.pos.x = posx; // copy the data into a MyVertex structure
   aVertex.pos.y = posy;
   aVertex.pos.z = posz;
   vertices.push_back(aVertex); // FEATURE: add the latest vertex to the vector without worrying how the memory gets allocated to store it
   // Note: the data from aVertex is *copied* into the vector's memory allocation. You can reuse aVertex to hold the next set of data
   // test for end-of-file
}

Step four: create a vertex buffer using the data just read in. For this illustration, the data to be read into the vertex buffer must be a contiguous block of memory. std::vector guarantees that will happen. Further, std::vector will automatically keep track of how many objects you pushed into it.

CreateVertexBuffer( myGraphicsBuffer );
// starting at the address &vertices[0], the MyVertex structures pushed into the vector will be in one contiguous block of memory
// further, vertices.size() will tell you how many MyVertex structures have been pushed. You don't have to count them yourself
CopyDataToFrom_And_HowManyBytes( &myGraphicsBuffer, &vertices[0], vertices.size() * sizeof(MyVertex) );

When that process is complete, you needn't worry about deleting or releasing the vector or the memory it used. That will all be taken care of when the vector goes out of scope.

Edited by Buckeye

Share this post


Link to post
Share on other sites

If you could post examples you feel would help me best understand how vectors work, that would be helpful. Vectors seems to be something very helpful use so I thought I might get the best understanding of it by seeing how their used by you guys at GDevs. I might have a few questions.

Am I really this predictable? That how I always go about all problems.

 

 


If you could post examples you feel would help me best understand how vectors work, that would be helpful. Vectors seems to be something very helpful use so I thought I might get the best understanding of it by seeing how their used by you guys at GDevs. I might have a few questions.

 

Have you used dynamic arrays before? Like this:

int* pIntegers = new int[100];
for(int i = 0; i < 100; i++)
{
    pIntegers[i] = i;
}

for(int i = 0; i < 100; i++)
{
    std::cout << pIntegers[i];
}
delete[] pIntegers;

std::vector is pretty much the same thing - just much safer (i.e. no memory-leaks), and with some additional out-of-the-box-functionality. You can (and possibly should) use them wherever you have been using plain "new type[count]" and so on until now:

std::vector<int> vIntegers;
vIntegers.reserve(100); // we know the amount of values beforehands, so we can tell this the vector to safe performance
for(int i = 0; i < 100; i++)
{
    vIntegers.push_back(i); // inserts i as the last element
}

for(auto integer : vIntegers) // c++11 range based for-loop, "integer" holds the current value in the vector
{
    std::cout << integer;
}

This code works identical to the first one. There is a few specialities to vectors which you can see here - like the way you can iterate them, "reserving" the memory before inserting a known amount of values, etc... but you'll learn them as you go.

 

Just a few (negativ-ish) things to keep in mind when using vectors:

 

- They can greatly reduce performance in debug-mode, when iterator debuggin is turned on and when you are iterating over them in a loop. Performance in "release" in Visual studio and likewise is identical to a plain array, so no need to worry here - just don't feel confused when you suddenly see a decrease in performance while debugging when changing from pointers/arrays to vector.

 

- As they are templates, they can slow down compile-time and increase EXE size. This does not happen in a huge extent anymore, and is not a huge problem anymore today - though using precompiled header files and using extern template declaration might help, if you are experiencing any of those problems (and have access to c++11 for the extern thingy).

 

Hope that helps.

 

With great power comes great responsibility. I knew this wasn't going to solve itself without a few difficulties but at least the potential problems don't appear too bad.

 

 

 

 

 

 

Show me what you were doing with this and possibly explain why?

(paraphrased for brevity)

#include <string>

#include <vector>

 

void mymethod()

{

   std::vector<std::string> labels;

 

   labels.push_back("up");

   labels.push_back("down");

   labels.push_back("left");

   labels.push_back("right");

 

   std::vector<std::string>::iterator it = labels.begin();

   for(; it < labels.end(); ++it)

      std::cout << *itr->c_str() << std::endl;

}

 

vectors are (arguably) the simplest container class in the STL. THAT's why they are used often. Their simplicity make them generally applicable to many types of problems. Think of a vector as a stack of single slot shelves, shelves that can store ANY object; but with the caveat that once you decide what object you want to store in them THAT'S the only kind of object you can place in them. Vectors are different from stacks as you can access any element at any position in the stack (random access).

 

I guess this explains why performance might take a hit using vectors. Hopefully my game won't suffer accessing a list of a few hundred at a time.

Share this post


Link to post
Share on other sites


I guess this explains why performance might take a hit using vectors. Hopefully my game won't suffer accessing a list of a few hundred at a time.

There's no bigger performance hit in a game than crashing. And my experience in the field has been that aggressive use of vectors (rather than raw memory) helps catch a lot of crash bugs early.

Share this post


Link to post
Share on other sites

I guess this explains why performance might take a hit using vectors. Hopefully my game won't suffer accessing a list of a few hundred at a time.

 

xeyedmary's post might have been a bit misleading -- for sequential reads, vector has the same performance characteristic as an plain old, C-style array. Random reads pay a single extra indirection which is going to be swallowed up and hidden by any modern CPU. The only performance issue that you can get into with a vector is when you grow it by adding extra items to it. Even then its the same cost you would pay to grow an array (except that native arrays don't support growing themselves, you have to relocate and copy, which is what vector knows to do), but vector, when it grows, grows extra so that it doesn't have to reallocate and copy every time. What's more, whenever you know how much room you're going to use, you can ask vector to reserve that amount of memory ahead of time, so that it never has to reallocate and copy while you are adding items. Long story short, vector is no slower than a plain-old-C array unless you're doing something evil, stupid, or ignorant, and since it does all that *and* allows you to grow it *and* handles all the dynamic memory management for you, there's no reason* not to use it.

 

* If you know the exact size you need, and you don't need to grow it ever, prefer std::array (which is an even thinner wrapper over an array than vector is, and like an array it can't grow). For simple storage and lists, prefer std::array and std::vector by default, unless A) you need to insert items at the front or in the middle (then look to std::list, std:deque) or B) you have a different kind of problem altogether, like something suitable to std::queue, std::map or std::set in all their variations. See http://www.cplusplus.com/reference/stl/ for the list of containers you can use.

Edited by Ravyne

Share this post


Link to post
Share on other sites

 


I guess this explains why performance might take a hit using vectors. Hopefully my game won't suffer accessing a list of a few hundred at a time.

 

xeyedmary's post might have been a bit misleading -- for sequential reads, vector has the same performance characteristic as an plain old, C-style array. Random reads pay a single extra indirection which is going to be swallowed up and hidden by any modern CPU. The only performance issue that you can get into with a vector is when you grow it by adding extra items to it. Even then its the same cost you would pay to grow an array (except that native arrays don't support growing themselves, you have to relocate and copy, which is what vector knows to do), but vector, when it grows, grows extra so that it doesn't have to reallocate and copy every time. What's more, whenever you know how much room you're going to use, you can ask vector to reserve that amount of memory ahead of time, so that it never has to reallocate and copy while you are adding items. Long story short, vector is no slower than a plain-old-C array unless you're doing something evil, stupid, or ignorant, and since it does all that *and* allows you to grow it *and* handles all the dynamic memory management for you, there's no reason* not to use it.

 

* If you know the exact size you need, and you don't need to grow it ever, prefer std::array (which is an even thinner wrapper over an array than vector is, and like an array it can't grow). For simple storage and lists, prefer std::array and std::vector by default, unless A) you need to insert items at the front or in the middle (then look to std::list, std::queue, std:deque) or B) you have a different kind of problem altogether, like something suitable to std::map or std::set in all their variations. See http://www.cplusplus.com/reference/stl/ for the list of containers you can use.

 

 

Hmm let's define stupid/ ignorant/ or evil.

 

Suppose I want to layer art resources dynamically in a game as a character moves through a map/environment. There are 3 layers and the character is printed on layer 2. The block tiles are printed on layers 1 and 3. I would need every single tile element of the vector/array to dynamically be printed individually on either layer 1 or 3 as conditions demand. Does this qualify for stupid? 

Edited by LAURENT*

Share this post


Link to post
Share on other sites

Figuring out what tiles are where is highly unlikely to be your bottleneck in any event.

 

That said, to be maximally efficient, I would create a vector, or possibly a std::array, with dimensions Width, Height, Depth, where Depth is the 3 layers you describe. I would walk all of (the visible portion of) layer 1 in row-order, then the same for layer 2, and for layer 3. With proper declaration of the vector or array, that will be as efficient as possible.

 

The declaration would look like this for std::array:

std::array<std::array<std::array<TILE_STRUCT, Width>, Height>, Depth> tiles;

 

Or for vector:

std::vector<std::vector<std::vector<TILE_STRUCT>>> tiles; // then populate the vectors appropriately, using reserve() to pre-allocate memory.

 

 

That's for a somewhat niave "I'm just going to carve out a square of this to draw" approach. If I were really needing efficiency (say, with significantly more than 3 layers, or a variable number of layers) I would then organize the data into a 2D grid of map sections a few tiles on a side (probably between 4x4 and 16x16) where the idea would be that I would only ever load the sections I had to draw. The section itself would be a linked-list to another 2D section containing the next layer up, and you could add as many layers as you needed.

 

Then, when rendering I would find all the sections that are in view, including their layers, then walk all of that per-layer building up a draw list, adding an appropriate Z-depth based on the layer. Build the list from the upper-most-layers to the base to take advantage of early-z rejection on the GPU.

 

The declarations would look something like this:

 

typedef std::array<std::array<TILE_STRUCT, 4>, 4> tiles_section; // create a type of a section of tiles that's 4x4;

 

std::array<std::array<std::forward_list<tiles_section>>> map_base_sections; // I'm going to hand-wave here, you can use things other than forward_list, and you need to figure out where you want to store your upper sections, and also how you'll manage lifetimes (e.g. with unique_ptr or scoping, etc).

 

 

But that's if you really need the speed -- almost certainly the 'naive' way is sufficient for most uses.

Share this post


Link to post
Share on other sites

There are so many uses for vectors in games programming alone. My most recent uses were for 2D level editing with SFML (I'm relatively new to games programming).

 

The first used 2 2D vectors, one storing Sprites and the other storing chars. The basic idea was that the program would read from a text file of arranged chars and store them in a vector, and then change the corresponding Sprite in the other. This was pretty slow, but it worked reasonably well.

 

The second use was today, using a single 1D vector and a single Sprite. In this one, the Sprite was set up with all the necessary properties, like a texture and a scale factor, then pushed back into the vector and re-formatted. The main properties were then listed in a specifically formatted text document for saving and loading the same formation of Sprites every time without issue. This was massively faster, and allowed for things like rotation, scaling, (theoretically) any size tilesheet and freely placed tiles. I then wrote a custom level editor using this, and a separate, lightweight class for using the files from the level editor in practically any other SFML project I want to work in.

 

 

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement