Sign in to follow this  

Noob array question

This topic is 3463 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

If I have a class that has an array member, is there any way to declare the size of the array through the class constructor? Or am I stuck using vector? Thanks. header
#ifndef TEXT_H
#define TEXT_H

class Text
{
public:
  Text (int size);
private:
  int blah[]; // size of the array passed through constructor
};
#endif


cpp

#include "text.h"

Text::Text(int size)
{
}

Share this post


Link to post
Share on other sites
yes

but btw, your array needs to be "int* blah", then in the constructor, put "blah = new int[size_here]"

Edit:

So your source would look like this:

Header

#ifndef TEXT_H
#define TEXT_H

class Text
{
public:
Text (int size);
private:
int* blah; // size of the array passed through constructor
};
#endif




Source

#include "text.h"

Text::Text(int size)
{
blah = new int[size];
}

Share this post


Link to post
Share on other sites
You have to use a vector.

If you could define the size of the array in the constructor that would go against the requirement that all instances of a class have the same size.

Oh, and please don't tell me you're writing a string class. Because there already is one, its called std::string, std::wstring

Share this post


Link to post
Share on other sites

class Text
{
private:
int* blah;
public:
Text(int size)
{
blah = new int[size];
}

~Text()
{
delete [] blah;
}
};




I haven't compiled this to try it, but it looks right. Also, if the name of the class is anything to go by, you want to store an array of characters... and I'd use an array of chars instead of an array of integers, mostly because it just makes more sense.

@fpsgamer: I think it works here because you're storing a pointer to an array? I'm doing pretty much the same thing in my own code and it works fine.

Share this post


Link to post
Share on other sites
Quote:
Original post by Twisol
@fpsgamer: I think it works here because you're storing a pointer to an array? I'm doing pretty much the same thing in my own code and it works fine.


Ya, storing a pointer and using a dynamic allocation works too. But std::vector is "nicer". As I said before if the user intends to represent text then std::string would be best.

Share this post


Link to post
Share on other sites
use vector...

arrays are messy, and are not able to be dynamically resized without full recreation of the array.

Vectors are in the standard libraries, work better and are cleaner to use in code.

Share this post


Link to post
Share on other sites
Quote:
Original post by lordcorm
yes

but btw, your array needs to be "int* blah", then in the constructor, put "blah = new int[size_here]"

Edit:

So your source would look like this:

Header
*** Source Snippet Removed ***

Source
*** Source Snippet Removed ***



ah ok, thanks :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Kalten
arrays are messy, and are not able to be dynamically resized without full recreation of the array.


False. You can malloc more memory on to the end of an array.

Edit: Sorry, its realloc().

Share this post


Link to post
Share on other sites
Quote:
Original post by lordcorm
Quote:
Original post by Kalten
arrays are messy, and are not able to be dynamically resized without full recreation of the array.


False. You can malloc more memory on to the end of an array.

Edit: Sorry, its realloc().


If realloc cannot acquire n contiguous bytes past the end of your current m byte allocation, it simply creates a new buffer of m + n bytes, copies the data, and frees the original allocation.

In C++ we we prefer not to use C memory allocators since they are incompatible with non-pod types. So this allocator should be avoided.

You should note however that the C++ does not have an equivalent to realloc. Bjarne Stroustrup explains what to do instead here (hint: it has something to do with std::vector).

Share this post


Link to post
Share on other sites
Are vectors generally better? The reason I am considering array now is because I'm doing A* pathfinding and I have it implemented now as vectors holding the information. The problem is that it is quite slow and I thought if I switched over to arrays instead of vectors it would improve the calculation time.

Or is the difference between vector and array for computation speed not different? Since this question is probably heavily affected by the circumstance I am using them under a quick description. I have about 5 vectors as of right now holding, x/y positions, costs, etc ( all ints). I have to use push_back each time I add a new step to the path I'm finding ( can get quite large, in the hundreds at least). So if I went with arrays I would avoid the push_backs in exchange for some memory space. Would this change make a big difference speed wise or should I look elsewhere for possible bottle necks? Thanks.

Share this post


Link to post
Share on other sites
Vectors are not necessarily slow, but arrays are faster. Using a vector would make your program a little less error prone, as if you tried to go over the array index amount, you would be slapped with a buffer overflow.

So, as said above, i would go with a vector.

Share this post


Link to post
Share on other sites
Speaking from almost no experience, I don't think std::vector is your problem. If you want to make your vector create enough space for however much you want at initialization, just do:


std::vector<int> myvec(1000);


which achieves the same effect as dynamically allocating an integer array of 1000. myvec.reserve(1000); does the same, except after initialization. Vector really makes things a lot easier, and if you have enough room in the capacity you've reserved, a push_back is no different from figuring out the next unused array index location and writing to it.

Share this post


Link to post
Share on other sites
Quote:
Original post by absolute
Are vectors generally better?


As a rule of thumb: In C++ always prefer std::vector.

Quote:
Original post by absolute
Or is the difference between vector and array for computation speed not different?


These questions start to go away once you take time to examine what exactly std::vector is.

However in the meantime you can simply take our word for it that std::vector is as fast as an array. That is because std::vector is an array. A much safer one at that.

Further reading: Why should I use container classes rather than simple arrays?

Share this post


Link to post
Share on other sites
Quote:
Vectors are not necessarily slow, but arrays are faster.
How/why/when are (raw) arrays faster?
Quote:
I have about 5 vectors as of right now holding, x/y positions, costs, etc ( all ints). I have to use push_back each time I add a new step to the path I'm finding ( can get quite large, in the hundreds at least).
push_back() always has the potential to be costly. The actual cost will depend on the circumstances and on the particular implementation being used, but if you're worried about it, there are approaches you can take that will minimize or eliminate the need for frequent calls to push_back(). (You should still use std::vector though; it almost certainly won't cost you anything, and you'll gain - among other things - automated clean-up of allocated resources, and at least the option of bounds-checking for debugging purposes.)

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
Quote:
Vectors are not necessarily slow, but arrays are faster.
How/why/when are (raw) arrays faster?



How: Using a Vector, you need to make a method call (1 cpu instruction "call") each time you want to add something to your Vector. push_back(), also has some extra overhead stuff it does such as incrementing counters, reallocing a new spot *each* time you push_back(). Then it will add what you want to the array.

Doing "myarray[1] = MyValue" is one cpu instruction "mov".

When: Always.

Why: Same has How.

As i said above, its fast, but not by much, but its there for an options if you want to save cpu calls, that is, if you want to sacrifice some managed security you get with a Vector.

Share this post


Link to post
Share on other sites
Quote:
Original post by lordcorm
Quote:
Original post by jyk
Quote:
Vectors are not necessarily slow, but arrays are faster.
How/why/when are (raw) arrays faster?



How: Using a Vector, you need to make a method call (1 cpu instruction "call") each time you want to add something to your Vector.

If you are using operator[], it's no slower than a raw array (assuming normal implementation).
Quote:
push_back(), also has some extra overhead stuff it does such as incrementing counters, reallocing a new spot *each* time you push_back(). Then it will add what you want to the array.

Yes, but that can't be considered to be slower than doing push_back on an array, because that operation doesn't even exist on arrays. Coding your own version is very likely to be slower than the std::vector implementation.
Quote:
Doing "myarray[1] = MyValue" is one cpu instruction "mov".

Try doing that operation and then doing the same for a vector, using the same operator, and compile the code (with optimizations on, of course). Check the assembly code. I think you'll see that there aren't any differences. Note that if you are using Visual Studio, you'll first have to disable the Microsoft-specific extension that turns operator[] into function at(), which is slower.
Quote:
When: Always.

There is only one instance where vector is slower than an array, and that is during initialization since vector always calls the constructors for allocated items while arrays don't. I have only ever seen that be a problem once, in an extremely specialized application.

Share this post


Link to post
Share on other sites
Quote:
Original post by lordcorm
[...] reallocing a new spot *each* time you push_back(). Then it will add what you want to the array.


I was under the impression that if you reserve()d enough from the start (or just passed a reserve size in the constructor) it wouldn't reallocate unless you went over the reserved amount.

Share this post


Link to post
Share on other sites
Quote:
Original post by Twisol
Quote:
Original post by lordcorm
[...] reallocing a new spot *each* time you push_back(). Then it will add what you want to the array.


I was under the impression that if you reserve()d enough from the start (or just passed a reserve size in the constructor) it wouldn't reallocate unless you went over the reserved amount.


@Twisol

You're correct. In fact insertions actually run in amortized constant time, in spite of the buffer expansion that occurs when you exceed capacity. In regards to that I refer you again to the dynamic array data structure.

Share this post


Link to post
Share on other sites
To get over the pointer-to-allocated-memory issue... why is it so much worse than std::vector ? The above implementation proposed by lordcorm, while longer, is still quite simple:

class Text
{
public:
Text (int size) : blah(new int[size]) {}
private:
int* blah;
};


However, it leaks memory, because that memory you allocate is never deallocated. Then, you have Twisol's proposal, which does not leak as much, but still creates problems when using the assignment operator or copy constructor:

class Text
{
private:
int* blah;
public:
Text(int size) : blah(new int[size]) {}
~Text() { delete [] blah; }
};


A correct implementation would be:

class text
{
private:
int* blah;
int size;
Text();
void swap(Text &other)
{
std::swap(blah, other.blah);
std::swap(size, other.size);
}
public:
Text(int size) : blah(new int[size]), size(size) {}
Text(const Text & other) : blah(new int[other.size]), size(other.size)
{
std::copy(other.blah, other.blah + other.size, blah);
}
Text &operator=(const Text &other)
{
Text temp(other);
temp.swap(*this);
return *this;
}
~Text() { delete [] blah; }
}


This is longer and harder to get right (on the other hand, it works sanely, never leaks memory and is exception-safe). Besides, it's also not optimal (though it could be optimized with some additional work). By contrast, std::vector is also shorter to write, and you run less risks of leaking memory by not paying attention.

Quote:
Original post by Lordcorm
How: Using a Vector, you need to make a method call (1 cpu instruction "call") each time you want to add something to your Vector. push_back(), also has some extra overhead stuff it does such as incrementing counters, reallocing a new spot *each* time you push_back(). Then it will add what you want to the array.

Doing "myarray[1] = MyValue" is one cpu instruction "mov".

When: Always.

Why: Same has How.


Oh, please, don't be silly. This is like saying "gliders fly very slowly, therefore we should use bikes". Sure, appending elements to a vector does involve some overhead, but since one cannot append elements to an array, the comparison is utterly useless. Yes, vectors do it slowly and arrays don't do it at all, now can we move on to more significant comparisons?

As far as assigning elements, vectors are designed to be as fast as arrays (though you might have to do some compiler configuration to enable this). Also, you can get a pointer to the vector's contents and access those using the pointer, achieving performance equivalent to any other pointer-to-buffer approach you could imagine while still getting the memory management benefits.

As a side note, push_back does not allocate memory every time. Actually, the number of allocations is logarithmic in the number of insertions: inserting a thousand elements in an array will only take 10 allocations (even fewer if you reserved a reasonable amount ahead of time).

Share this post


Link to post
Share on other sites
Quote:
Original post by lordcorm
How: Using a Vector, you need to make a method call (1 cpu instruction "call") each time you want to add something to your Vector

Not true. operator[] is trivially inlined, making it *exactly* as expensive as if you'd used an array.

Quote:

. push_back(), also has some extra overhead stuff it does such as incrementing counters, reallocing a new spot *each* time you push_back(). Then it will add what you want to the array.

But since you *can't* do push_back at all on an array, this is no slower. If you want to compare performance, it only makes sense to look at the functionality they have in common. std::vector has some functionality that arrays don't have. push_back is one example.

Quote:

Doing "myarray[1] = MyValue" is one cpu instruction "mov".

Same as on a vector then.

Quote:

As i said above, its fast, but not by much, but its there for an options if you want to save cpu calls, that is, if you want to sacrifice some managed security you get with a Vector.

Wrong. And this is why it's generally a good idea to examine the code emitted by your compiler before making loud claims about how fast X is. 99% of the time, there really is no sacrifice or tradeoff involved. Most of the time, a vector just *is* better.

There are some cases where an array is more suitable, but they're the exception, rather than the rule.

Share this post


Link to post
Share on other sites
Quote:

Vectors are not necessarily slow, but arrays are faster.


Irrelevant.

Write the program first. If you later find your vector usage to be the bottleneck (which, for the various reasons mentioned above, is unlikely), then optimise.

Don't prematurely optimise.

Share this post


Link to post
Share on other sites
Quote:
Original post by absolute
I'm doing A* pathfinding and I have it implemented now as vectors holding the information.

Show us some relevant code. When implementing relatively "complex" algorithms like A*, it is far more important to choose the right datastructures (say, a hash_map instead of two arrays or something) than to be considered with nonexisting performance benefits of array vs. vector.

Even IF vector was slower than array, it could only be by a constant amount. This wouldn't radically improve your performance, whereas a different datastructure (once again, a vector is not fundamentally different than an array) could get you from O(n*n) to O(n log n) or even O(n). There is no point in trying to make things 1% faster when you can go from quadratic to linear. Don't micro-optimize.

Share this post


Link to post
Share on other sites
Quote:
How: Using a Vector, you need to make a method call (1 cpu instruction "call") each time you want to add something to your Vector. push_back(), also has some extra overhead stuff it does such as incrementing counters, reallocing a new spot *each* time you push_back(). Then it will add what you want to the array.
If you're comparing std::vector to a fixed-size array here, then the comparison is meaningless (since it's impossible to add new elements to a fixed-sized vector dynamically, it makes no sense to say that std::vector does this 'more slowly'). If on the other hand you're comparing std::vector to manual array management using pointers and new/delete, then you're going to end up doing similar work anyway if you want to add new elements, so the comparison is once again meaningless (at least without a reference implementation of your own with which to compare).

Also, a typical implementation of std::vector will not re-allocate every time you call push_back().
Quote:
Doing "myarray[1] = MyValue" is one cpu instruction "mov".
Are you sure that element access via operator[]() using std::vector (with all range-checking turned off) compiles to different code than element access using built-in arrays?

Anyway, these points have already been made by others in this thread, but I think they're worth hearing more than once.

Now that the points in your post have been addressed (several times over, in fact), I'll again pose the question: How/why/when are (raw) arrays faster?

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
If you're comparing std::vector to a fixed-size array here, then the comparison is meaningless (since it's impossible to add new elements to a fixed-sized vector dynamically, it makes no sense to say that std::vector does this 'more slowly').

Exactly. It's like saying C++ is slower than C because of virtual function calls.

Quote:
Original post by jyk
Also, a typical implementation of std::vector will not re-allocate every time you call push_back().

Such an implementation isn't even allowed, because the standard says that push_back on a vector must be of amortized constant time complexity.

Quote:
Original post by jyk
How/why/when are (raw) arrays faster?

I could imagine that a LOCAL array can be faster than a local vector, because you save one indirection. But this isn't the OP's scenario, so it's irrelevant to the discussion.

Share this post


Link to post
Share on other sites

This topic is 3463 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.

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