Sign in to follow this  
Ignifex

Just a simple 2D vector

Recommended Posts

Hi, I'm pretty new to C++, but an experienced AS programmer, and currently learning a lot about the ways C++ does things. I'm trying to make a simple 2D vector to save some classes in, but I can't seem to do it. Basically, I need multiple levels in which to save multiple classes and the amount of classes per level must be able to grow and shrink. To save just one level I would say like: vector<someclass*> classes(size); But then how do I make this into a 2D-vector? I know i need something like: vector<vector<someclass*>> With arrays it's pretty easy to do, but I don't get it yet when it comes to vectors. How do I do that? Thanks in advance.

Share this post


Link to post
Share on other sites
I have another question and I hope this one's less stupid. I want to put the vector inside a class. I allready read I can't set the size inside the class itself, so I declared the size in the constructor for the class, just using the same syntax as normal for declaring a vector. Now, the class with the vector is inside another class (and I really hope I know how to do that).
The problem is that my vector still doesn't have a size as if it weren't set. So it either doesn't do my constructor (I just used: myclass someclass to declare the class) or the size isn't set the way I did it.
What am I doing wrong? Thanks in advance.

Share this post


Link to post
Share on other sites
Should look something like this:

#include <vector>
#include <iostream>

class CInside
{
public:
CInside() : mVector(20)
{
}
int Size()
{
return mVector.size();
}
private:
std::vector<int> mVector;
};

class COutside
{
public:
COutside()
{
}
int Size()
{
return mInside.Size();
}
private:
CInside mInside;
};

int main()
{
COutside Outside;
std::cout << Outside.Size();
return 0;
}



Is there any major difference between your version and this?

Share this post


Link to post
Share on other sites
Quote:
Original post by Ignifex
I have another question and I hope this one's less stupid. I want to put the vector inside a class. I allready read I can't set the size inside the class itself, so I declared the size in the constructor for the class, just using the same syntax as normal for declaring a vector. Now, the class with the vector is inside another class (and I really hope I know how to do that).
The problem is that my vector still doesn't have a size as if it weren't set. So it either doesn't do my constructor (I just used: myclass someclass to declare the class) or the size isn't set the way I did it.
What am I doing wrong? Thanks in advance.


If i understood what you where saying you mean't something like this (with 2D vectors):


#include <vector>

struct containee {};

class contained {
public:

typedef std::vector< containee > vec1D;
typedef std::vector< vec1D > vec2D;
typedef vec2D::size_type size_type;

private:

vec2D matrix_of_containee;

public:

contained(size_type rows = 0,
size_type cols = 0,
const containee& c = containee())
: matrix_of_containee(rows, vec1D(cols, c)) {}

//la-la-la
};


class someclass {
contained c;

public:

typedef contained::size_type size_type;

someclass(size_type rows = 0,
size_type cols = 0,
const containee& c = containee())
: c(rows, cols, c) {}
};

Share this post


Link to post
Share on other sites
Ok Agony, I understand everything of your code, except this:
CInside() : mVector(20)
{
}
This is the declaration of the size of the vector, but I really don't recognise the syntax here. Just a single : ? And what are the bracelets for?
Thanks for your reply, I'll just try something like this.

<EDIT>
Ok I found this is the constructor.
But I need more in my constructor because the class uses other variables as well. Can I just set mVector(20) in my constructor?

Snk_kid, I don't really understand what your code does. What I see in a 2D-vector is simply a vector-a with some other vectors as every item in the vector-a.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ignifex
Ok, I understand everything of your code, except this:
CInside() : mVector(20)
{
}
This is the declaration of the size of the vector


Yes but if your using a vector of vector of some type to make a matrix then you probably wont to set the size of coloums/rows aswell like in my above code.

Quote:
Original post by Ignifex
but I really don't recognise the syntax here. Just a single : ?


It's called a constructor intializer list, it's how you intialize members & base classes prorperly.


Quote:
Original post by Ignifex
<EDIT>
Ok I found this is the constructor.
But I need more in my constructor because the class uses other variables as well. Can I just set mVector(20) in my constructor?


Intialize all your members in a intializer list.

Share this post


Link to post
Share on other sites
Hmm ok thanks! It's all working properly again now.
Just one final question:
Why is the vector set outside the bracelets? Can't it also just be set inside of them?

Share this post


Link to post
Share on other sites
Yeah, as snk_kid said, it's an initializer list. And it was an inlined constructor as well, but for a normal constructor, you can follow the function name and parameters by a colon, and then a comma separated list of constructors for your member objects, like this:

class CClass
{
public:
CClass();
CClass(int AnInt, float AFloat);
private:
int mInt;
float mFloat;
std::vector<int> mVector1;
std::vector<float> mVector2;
};

CClass::CClass() : mInt(0), mFloat(0.0f), mVector1(0), mVector2(4, 0.0f)
{
//Any additional stuff
}

CClass::CClass(int AnInt, float AFloat) : mInt(AnInt), mFloat(AFloat), mVector1(AnInt), mVector2(AnInt, AFloat)
{
//Any additional stuff
}


Also, like snk_kid said, I suppose you wouldn't be able to initialize the internal vector sizes without actually using code from within the constructor body itself, but you could still resize the outside vector (of vectors) to the proper size using the initializer list.

Also, just if you're curious, the reason vector<vector<int>> (without the spaces between the last two >s) doesn't work is because the compiler sees a shift operator (>>) instead of the two close brackets. The space makes it clear that it isn't a shift operator.

Share this post


Link to post
Share on other sites
Quote:
Original post by Ignifex
Why is the vector set outside the bracelets? Can't it also just be set inside of them?


Because intialization/construction is different from assigment even if the final result is the same, what i mean is this:

int i;

i = 10;


is different from this:

int i(10);

or

int i = 10; //implicitly invokes constructor


all built-in types and standard library types in c++ have constructors to intialize instances.

The intializer list allows you to use the members constructors to intialize a type's members.

EDIT: with assignment the variable may have had a previous value

Share this post


Link to post
Share on other sites
Quote:
Original post by Ignifex
Just one final question:
Why is the vector set outside the bracelets? Can't it also just be set inside of them?
Initializer lists are more efficient in some cases. In most cases, it's trivial, but sometimes, you could cause a major performance loss by not using an initializer list. Basically, if you have a class that has a complex default constructor as a member, then when you construct the outer class, the inner member class's default constructor will get called, which could take a while. Then, after doing the default construction, you might do other stuff that member object that takes more time. With an initializer list, however, the default constructor isn't used, and it skips to initializing it precisely how it needs to be. Consider this example:

class CInside
{
public:
CInside(const std::string& FileName = "Default.dat");
void GetFileData(const std::string& FileName);
private:
std::vector<char> mData;
};

CInside::CInside(const std::string& FileName)
{
GetFileData(FileName);
}
void CInside::GetFileData(const std::string& FileName)
{
//Open file, and read in all data into mData, then close file
}

class COutside
{
public:
COutside(const std::string& FileName);
private:
CInside mInside;
};

COutside::COutside(const std::string& FileName)
{
mInside.GetFileData(FileName);
}



What will happen here is that when you create a COutside object, the mInside member will get its default constructor called, thus opening "Default.dat" and reading all the data in. This could take a while if it is a large file. Then, immediately after doing all that, the COutside constructor calls GetFileData(), and another file is opened and read. Twice as much work done, when it isn't needed. If you change the COutside constructor to this, though:

COutside::COutside(const std::string& FileName) : mInside(FileName)
{
}
then it will call mInside's constructor with the proper filename, and totally skips the default step. More efficient.

Share this post


Link to post
Share on other sites
Thanks Agony/snk_kid, you're both really great!
To Agony:
second point: Yes, I allready realised that, but since the vectors inside the vectors are supposed to start at size 0, that's no problem at all.
third point: So that's why! I should've figured that one out myself. I hardly use < and > operators, so I'm no used to their combination together. Thanks for the explanation here.
To snk_kid:
Ok, right. It all makes sense to me now. Thanks again.

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