C++ - How do I put a static array inside my array? - c++

I apologize for the total noob question, but I just cannot find an answer. I googled, searched here, searched C++ array documentation, and some C++ array tutorials.
The question is simple. Why does
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
... //do stuff. Imagine a loop here, and BIG array - I'm just simplifying it for StackOverflow
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
return 0;
}
result in an error?
1>arraytest.cpp(11): error C2059: syntax error : '{'
How do I put a static array inside my array? I realize I could set each item individually, but there has to be a better way.

Built-in arrays in C++ have their problems, and not being assignable does make them rather inflexible. I'd stick with std::array, a C++11 container that emulates a better style of array, which allows a somewhat similar syntax to what you're looking for:
std::array<int, 3> arr{{1, 2, 3}};
std::array<int, 3>{{4, 5, 6}}.swap(arr);
//now arr is {4, 5, 6}
Here's a full sample. The trick is to use the initializer list on a newly-constructed array and then swap that with yours. I believe that the next C++ update is going to remove the need for the double braces as well, which makes it an even closer match to familiar syntax.

Initializer lists can be used just for initialization :)
Like when you declare your variable:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}}; // this is ok
You have to remove this:
pixelarray = {{1,0,-1},{1,0,-1},{1,0,-1}};
And assign new values manually (i.e. pixelarray[x][y] = or with a memcpy(pixelarray, <some other array>, sizeof(pixelarray)))

If you don't want to assign each individual element manually, you can do this:
short pixelarray2[3][3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
memcpy(pixelarray, pixelarray2, sizeof(pixelarray));
As #Nick points out: initializer lists are not for assignment.

Arrays are not assignable, so the short answer is that you can't do exactly what you're asking for. The most direct way to do something similar enough for most purposes is probably a 2D array class that acts as a wrapper around a std::vector, on the order of the one I posted in a previous answer.
If you insist on staying with C-style arrays, one possibility would be to use a pointer:
int main() {
typedef short array[3];
array pixelarray0[3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
array pixelarray1[3] = {{1,0,-1},{1,0,-1},{1,0,-1}};
array *pixelarray = pixelarray0;
// when needed:
pixelarray = pixelarray1;
}

Taking this question from a straight C context, you can have different constant arrays and just copy them with memcpy:
typedef short TArray[3][3];
const TArray a1 = {{1,1,1},{0,0,0},{-1,-1,-1}};
const TArray a2 = {{1,0,-1},{1,0,-1},{1,0,-1}};
// ...
TArray a;
memcpy( a, a2, sizeof(TArray));
Or you could exploit C99 struct copying, but I'd consider this a dangerous hack because the structure might be padded to be larger than the array, or have a different alignment.
typedef struct {
TArray arr;
} TDummyArray;
// ...
TArray a;
*(TDummyArray*)a = *(TDummyArray*)a2;

Once you have declared your array there is no way to use the assignment operator to reassign the entire content of the array.
So to change the contents or your array after this:
short pixelarray[3][3] = {{1,1,1},{0,0,0},{-1,-1,-1}};
You need to either loop through the array and manually change each value, or you something like std::memcpy to copy your new values over.
But you should really not be using an array in the first place, use some fromthing the std collections library instead like std::array or std::vector. Only use arrays if you have a really really good reason why you can't use a collection.

Related

C++ Initialise emtpy array based on template defined length and type

Good whatever part of the day you're reading this!
I've been trying to implement my own version of an std::deque-like container. I thought it would be possible to use templates to customise the size and type of the inner array 'blocks', but I can't seem to get the syntax right. Or at least I think what I'm doing is somehow possible.
template<typename T, int ChunkSize>
class ChunkList
{
public:
ChunkList()
{
T first[ChunkSize] = new T[ChunkSize];
// error: array must be initialized with a brace-enclosed initializer
m_ChunkPointers.push_back(first);
}
private:
// store pointers to the chunks
std::vector<T[]> m_ChunkPointers;
};
int main()
{
ChunkList<int, 4> cl = new ChunkList<int, 4>();
}
// compiled with g++ on a windows x64 machine
I found a Stack Overflow answer relating to the brace-enclosed initializer but I don't know how to initialize those with the template syntax.
The only other solution I can think is is using something like malloc(sizeof(T) * ChunkSize) and then casting that to an T[] or something.
Either way any help/advice would be greatly appreciated, always happy to learn new things!
PS: Even if there is a way more efficient solution I'd still like to know if there is a way to make templates behave the way I intend to here, or rather why this isn't valid.
You are already using std::vector why not a proper container for the chunks too?!?
template<typename T, int ChunkSize>
struct ChunkList {
ChunkList() : m_Chunks(1) {}
private:
std::vector<std::array<T,ChunkSize>> m_Chunks;
};
// store pointers to the chunks - You do not want to store pointers, you want to store arrays. You attempted to store them on the heap, but that complication is totally unnecessary, because they are of fixed size and std::vector does already manage its elements in dynamically allocated memory.
We have a few problems here.
1: In main you wrote ChunkList<int, 4> cl = new ChunkList<int, 4>();
This will not work because new will return a ChunkList* not a ChunkList you need to write ChunkList<int, 4>* cl = new ChunkList<int, 4>(); or ChunkList<int, 4> cl{}; depending on the hact if you need an object or a pointer to an object
2:std::vector<T[]> m_ChunkPointers; declares a vector of empty arrays. I think you menat to write std::vector<T*> m_ChunkPointers; storeing pointers (to the start of the arrays.)
3: T first[ChunkSize] = new T[ChunkSize]; needs to be T *first = new T[ChunkSize];
You mixed together the T x[N]; sintax and the T*x=new T[N]; syntax. the first will create an array on the stack the second will create one array, living until the end of the function on the heap, living until you detete it.
Note: Welcome to C++. In C++ the variables the object themself, not referances/pointers. You need to manage the lifetimes of the objects living in the heep. If you don't want to delete every object you used I suggest to take a look on unique_ptr and shared_ptr

need to create multiple dynamic arrays in c++

I need to create a number of arrays of a certain object where the number I need is dependent on a separate variable the best way to explain it is with a psudo code example:
int num = 4;
for(int i=0;i<num;i++){
object_type arrayi [dynamic size];
}
So i need 4 arrays each with the names array0,array1,array2, and array3 and they must all be dynamic arrays.
Is there anyway to do this in C++?
std::array<std::vector<object_type>, 4> array;
for (auto & v : array)
v.resize(dynamic_size);
The names are array[0], array[1], etc... instead of array1, array2, etc... But who cares? If you absolutely must have those names, then Cassio's answer is your best bet.
Pre C++11 alternative:
std::vector<object_type> array[4];
for (size_t i=0; i<4; ++i)
array[i].resize(dynamic_size);
If you want a variable number of arrays, then you can use a vector of vectors, and actually, the initialization for that is even easier. It doesn't require a loop, you can do it in the constructor.
std::vector<std::vector<object_type>> array(num, std::vector<object_type>(dynamic_size));
Yes, use std::vector<object_type> instead. You can resize to an arbitrary size.
Otherwise for arrays you can use dynamic allocation with
ObjectType* myArray = new ObjectType[number];
but using std::vector instead is recommended.
If there is a way to dynamically create variables like the way you want within C++, I haven't heard of it.
If performance is an issue and you need to construct a bunch of 1-d arrays (rather than an array of arrays or a vector of arrays) then you could do code generation at build time to make as many as you want. That's outside of C++ though; it's a pre-build command that outputs a C++ text file.
If performance isn't an issue, then constructing a vector of arrays like Benjamin has done will work great.
Reading the OP again, it seems to me that the number of arrays is not known at compile time. In this case, you can use a std::vector<std::vector<object_type>>:
#include <vector>
// ...
// int num = ???, dynamic_size = ???;
std::vector<std::vector<object_type>> vs(num);
for (auto& v: vs)
v.resize(dynamic_size);
then you can use vs[i][j] to get a reference to the j-th element of the i-th array (vector).
Piece of advise: Don't use this (std::vector<std::vector<double>>) for linear algebra matrices.
Bonus: In C++14 (actually this is a C99 feature that some compilers allow in C++ as an extension) you'll be able to do this:
#include <vector>
// ...
// int num = ???, dynamic_size = ???;
std::vector<object_type> vs[num];
for (auto& v: vs)
v.resize(dynamic_size);
For more information see this post.

How to make a number returned from a function be used for defining no of elements in an array?

I am using Opencv/c++.
I get the number of frames in a video using the function
int noOfFrames = cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_COUNT );
I have also declared an array int Entropy[noOfFrames];. But as the variable noOfFrames is non-const, it gives an error.
I even used const_cast for this but still it gives an error. I want the length of the array to be equal to the no of frames of the video.
How can I do it ???
You can't declare a static array with a dynamic size. You need a dynamic array:
int* Entropy = new Entropy[noOfFrames];
// use here, same as array
delete[] Entropy;
But using a vector is just easier:
std::vector<int> Entropy(noOfFrames);
// use here, same as array and more
// no need to clean up, std::vector<int> cleans itself up
In C++, you cannot do that because the size of a c-style array should be a compile-time constant1.
Anyway, you have a superior alternative : use std::vector
std::vector<int> Entropy(noOfFrames);
Even if you have compile-time constant, I would not suggest you to use int arr[size] which is c-style array. Instead I would suggest you to use std::array<int,size> arr; which is again far superior solution.

std::vector with pointers to static arrays with custom types

I have something like this:
typedef int customType[10];
And I want a function like this
std::vector<customType*>& myFunc();
But there are some problems.
1) I need to allocate memory for every pointer to customType in the vector (do I?)
and doing
std::vector<customType*> A;
//some code to get length
for (i = 0; i < length; i++)
{
A[i] = new customType;
}
is wrong because of an error:
IntelliSense: a value of type "int *" cannot be assigned to an entity of type "customType*"
2) In common, is it a good way to store such data? Maybe I should make an array of 1 dimension with everything stored in one line and use something like
A[i*innerLength+j]
to access elements?
Your code won't work because A[i] is of type int (*)[10] and the new expression is of type int*, either change A to std::vector<int*> or wrap your array in a class or struct:
struct customType {
int data[10];
};
Then you can use either std::vector<customType> (preferably) or std::vector<customType*>.
std::vector<int[10]> wont work because arrays in C and C++ are not assignable which is a requirement for std::vector.
I would generally recommend using something like the below and doing the array indexing yourself.
std::vector<int> vals(row_size*col_size, 0);
At really large sizes it may be better to break it up. It's just a lot of contiguous memory to allocate in a block. "Really large" is pretty subjective, and you probably can get away with a lot larger sizes than most people would expect. Let the profiler tell you when it's a problem.
If you have access to C++11, then this would be another option.
TEST(array)
{
typedef std::array<int,10> Foo;
typedef std::vector<Foo> Foos;
Foos foos(10, Foo());
}

Creating a dynamic sized array of fixed sized int arrays in C++

For some reason this is giving me more trouble than i thought...
int *myArray[3];
myArray = new int[mySize];
does not work...
I've used a typedef before in a similar manner and it worked perfectly, but this time i dont want to create the typedef
One might be tempted to do this:
::std::vector<int[3]> myArray;
Because vector is so nice for dynamically sized arrays. Unfortunately, while that declaration works, the resulting vector is unusable.
This will be just as efficient, if you have ::std::array (a C++11 feature) and it will actually work:
::std::vector< ::std::array<int, 3> > myArray;
If you can do this, I would highly recommend it. vector is much nicer and safer to deal with than an array you have to allocate yourself with new.
Otherwise, try this:
typedef int inner_array_t[3];
inner_array_t *myArray = new inner_array_t[mySize];
And since you don't want to use a typedef for some odd reason, you can unwrap it like so:
int (*myArray)[3] = new int[mySize][3];
int (*myArray)[3] = new int[mySize][3];
?
int *myArray[3];
This means "myArray shall be an array of three pointers-to-int".
You presumably wanted "myArray shall be a pointer-to-(array of three ints)". That is spelled int (*myArray)[3].
This sort of thing is much easier with typedefs.
typedef int datum[3];
datum* myArray = new datum[mySize]; // no fuss, no muss.
But seriously, just use std::vector. And make an actual struct for your group-of-three-integers. Or, if it really should behave like an array, use boost::array so that you at least get the behaviour of a first-class type.