c++ allocate array syntax question - c++

You can write like this:
int test[] = {1,2,3,4};
but what if you want to use a pointer and allocate it with new?
int *test2;
test2 = new int[]{1,2,3,4};
This does not work, what is the syntax or is it possible?

This is one of the short-comings of current standard C++. Initialization is not uniform. Your best hope is uniform initialization in C++0x, but for the mean while you can assign the values after creating the array, e.g.
int *test2;
test2 = new int[4]; // Note that you still have to specify the size in C++0x
test2[0] = 1;
test2[1] = 2;
test2[2] = 3;
test2[3] = 4;

If you compiler supports C++0x
int *test2;
test2 = new int[4] {1,2,3,4}; // Initializer list in C++0x
would work. However you should always use std::vector instead of C style arrays while writing good C++ code.

The first syntax is called aggregate initialization, and you cannot apply it to a dynamically allocated array. When allocating dynamically you must provide the number of elements that you want to initialize inside the square brackets and (optionally) the default value in parenthesis (if you want the array initialised). The default value will be the same (if present) for all elements.
You may want to look into the boost::assign library that may have support for this type of initialization (not sure). Alternatively you can (at the cost of more code) do it yourself for POD types:
int * array = new int[4];
{
int values[] = { 1,2,3,4 };
memcpy( array, values, sizeof(values) );
}
Or for non-pod types:
type * array = new type[4];
{
type values[] = { 1,2,3,4 }; // assuming type(int) constructor
std::copy( values, values+4, array ); // better to use some magic to calculate size
}
At any rate both of those solutions require allocating locally and the copying (bit-size/c++) into the dynamically allocated memory.

Related

Calculate length of double pointer array

I have a double pointer Array of a structure:
typedef struct Position{
int x;
int y;
} Position;
Position** array = (Position**)malloc(sizeof(Position*)*10); //10 elements
array[0] = (Position*)malloc(sizeof(Position*));
array[0]->x = 10;
array[0]->y = 5;
Can I calculate the length of set array and if so, how?
The normal way for arrays does not work :
int length = sizeof(<array>)/sizeof(<array>[0]);
Once you have dynamically allocated an array, there is no way of finding out the number of elements in it.
I once heard of some hacky way to obtain the size of a memory block, (msize) which would allegedly allow you to infer the size of the data within the block, but I would advice against any such weird tricks, because they are not covered by the standard, they represent compiler-vendor-specific extensions.
So, the only way to know the size of your array is to keep the size of the array around. Declare a struct, put the array and its length in the struct, and use that instead of the naked array.
As you marked the question as C++, I would suggest that you use std::vector, then, after you "allocated some memory" (or requested some memory to allocated by std::vector constructor or by using push_back, or resize), you can simply get the size back using by using std::vector::size.
typedef struct Position{
int x;
int y;
} Position;
std::vector<Position> array(10);
array[0].x = 10;
array[0].y = 5;
size_t size = array.size(); // will be 10
Having only a pointer to some memory block, you cannot defer the size of this memory block. So you cannot defer the number of elements in it.
For arrays of pointers, however, you could infer the number of elements in it under the following conditions:
make sure that every pointer (except the last one) points to a valid object.
for the last pointer in the array, make sure that it is always NULL.
Then you can derive the length by counting until you reach NULL.
Maybe there are some other similar strategies.
Solely from the pointer itself, however, you cannot derive the number of elements in it.
Old question, but in case someone needs it:
#include <stdio.h>
...
int main()
{
char **double_pointer_char;
...
int length_counter = 0;
while(double_pointer_char[length_counter])
length_counter++;
...
return 0;
}

Instantiating a 3D array in C++ using parameters

Sorry if this is a noob question, but I'm currently learning C++. I have a function that takes in several parameters - I would like to use those parameters when creating a 3D int array.
void* testFunction(int countX, int countY, int countZ)
{
const int NX = countX;
const int NY = countY;
const int NZ = countZ;
int* data_out = new int*[NX][NY][NZ];
// The above line throws the error on "NY" - expression must
// have a constant value
}
From various posts I've learned that you must allocate the array first but I guess I'm doing that wrong? How do you properly initialize a multidimensional array. Also, why does the initialization require a pointer?
To explain the error: C++ requires a name of a type in its new operator. A name of a type cannot have runtime dimensions, because all types in C++ are static (determined at compilation time).
For example, this allocates 3 elements of type int[4][5]:
new int[3][4][5];
Another example: this allocates NX elements of type int[4][5]:
new int[NX][4][5];
An incorrect example: this would allocate NX elements of type int[NY][NZ], if C++ had support for "dynamic" types:
new int[NX][NY][NZ];
To allocate a 3-dimensional array, or something that looks like it, you can use std::vector:
std::vector<std::vector<std::vector<int>>> my_3D_array;
... // initialization goes here
my_3D_array[2][2][2] = 222; // whatever you want to do with it
To make the syntax less verbose, and streamline the initialization, use typedef (or here using, which is the same):
using int_1D = std::vector<int>; // this is a 1-dimensional array type
using int_2D = std::vector<int_1D>; // this is a 2-dimensional array type
using int_3D = std::vector<int_2D>; // this is a 3-dimensional array type
int_3D data(NX, int_2D(NY, int_1D(NZ))); // allocate a 3-D array, elements initialized to 0
data[2][2][2] = 222;
If you want to return this array from your function, you should declare it; you cannot just return a void pointer to the data variable. Here is a syntax of a declaration:
using int_1D = std::vector<int>;
using int_2D = std::vector<int_1D>;
using int_3D = std::vector<int_2D>;
int_3D testFunction(int countX, int countY, int countZ)
{
int_3D data(...);
...
return data;
}
That is, instead of using new, just use std::vector<whatever> as if it were any other type.

How to dynamically create a c++ array with known 2nd dimension?

I have a function:
void foo(double[][4]);
which takes a 2d array with 2nd dimension equal to 4. How do I allocate a 2d array so that I can pass it to the function? If I do this:
double * arr[4];
arr = new double[n][4];
where n is not known to the compiler. I cannot get it to compile. If I use a generic 2d dynamic array, the function foo will not take it.
As asked, it is probably best to use a typedef
typedef double four[4];
four *arr; // equivalently double (*arr)[4];
arr = new four[n];
Without the typedef you get to be more cryptic
double (*arr)[4];
arr = new double [n][4];
You should really consider using standard containers (std::vector, etc) or containers of containers though.
typedef double v4[4];
v4* arr = new v4[n];
Consider switching to arrays and vectors though.
I know it may not be what OP has intended to do, but it may help others that need a similar answer.
You are trying to make a dynamic array of statically success array. The STL got your solution: std::vector and std::array
With these containers, things are easy easier:
std::vector<std::array<int, 4>> foo;
// Allocate memory
foo.reserve(8);
// Or instead of 8, you can use some runtime value
foo.reserve(someSize);
// Or did not allocated 8 + someSize, but ensured
// that vector has allocated at least someSize
// Add entries
foo.push_back({1, 2, 3, 4});
// Looping
for (auto&& arr : foo) {
arr[3] = 3;
}
// Access elements
foo[5][2] = 2;
Alternatively to creating a new type and occupying a symbol, you can create a pointer to pointer, and do it like that:
double **arr = new double*[j];
for (int i = 0; i < j; ++i)
{
arr[i] = new double[4];
}
whereas j is the int variable that holds the dynamic value.
I've written a simple code that shows it working, check it out here.

C++ possible #define something but used before

I am wondering if this is possible (for very easy use in project)
Say:
// array size (COUNT)
int foo[COUNT];
// values
foo[0] = 1;
foo[1] = 43;
foo[2] = 24;
// define (or equivalent) its size at the end
#define COUNT 3
(This is by design, so I don't have to fine tune it whenever I change the arrays length)
Thanks.
Edit:
What I am looking for is defining the size of the array after it has been filled with values. In the example I only know that it is 3 when I put values. So I could add 4 more "foo"s and only need to change the #define below.
Next Edit:
// this is the idea, can this be possible? or even a "forward" declared
int foobar = THEVALUE
// way further down
#define THEVALUE 5;
int foo[] = {1, 43, 24};
int const count = 3; // See the SO array FAQ for how to compute this.
A simple type safe way to compute size, not mentioned in the SO array FAQ (because it was written before C++11), is
int const count = end( foo ) - begin( foo );
where end and begin are the std namespace functions from the <iterator> header.
See the SO array FAQ for other ways.
Generally, in modern C++ it is preferable to use std::array (fixed size) and std::vector (dynamic size) over raw arrays. This is safer and with more rich functionality, including in particular assignment and the ability to check the size easily. Unfortunately std::array does not support a size inferred from the initializer, so in this you'd have to use std::vector even if the array size is meant to be constant:
vector<int> foo = {1, 43, 24};
// foo.size() gives you the size at any moment.
You could initialize array with initializer list, then you don't need to know its size at all:
int foo[] = { 1, 43, 24 }
int size = sizeof(foo) / sizeof(int); // if you do need to know size
EDIT:
For a more idiomatic C++11 see the answer above :)

Dynamic memory allocation...how about this type of inititlization?

To create an integer on heap and initialize it to a value 5, we do:
int* a = new int(5);
To create an array of 5 integers on the heap, we do:
int* a = new int[5];
But, if we want to create an array of 5 integers and initialize each of them to 10 in one single instruction, is it possible?
To make things more interesting, let us say that the array size will only be known at run time. How about then?
Also, I know this is a very trivial question, but I'm making this transition from Java and get confused at times with C++, so... if not initialized during declaration, then unlike in Java, C++ primitive data types are not initialized with default values, and contain garbage values, right?
But someone told me that if they are declared as global variables, then they are initialized to default values like in Java...is that true as well? Why?
I prefer:
std::vector<int> a = {10,10,10,10,10};
C++ is a very complex language, with many different (even contradicting) goals.
One of the ideas behind it was that you should not pay in efficiency what you don't need and this is what is behind the concept of uninitialized values.
When you write
int x;
the variable x is initialized if it's at global/namespace scope and instead is not initialized when the definition is in a local scope.
This happens not because who designed C is crazy (of course an initialized value is better) but because initialization at global/namespace scope is free from an efficiency point of view as it's done compile/link/loading time, not at runtime.
Initializing a variable in local scope instead has a cost (small, but non-zero) and C++ inherited from C the idea that shouldn't pay for it if you don't need it, thus if you want your variable initialized to any value simply says so with:
int x = 42;
Note however that an uninitialized variable is not simply "containing a garbage value", it's uninitialized and you are not allowed to read its content as such an operation is "undefined behavior".
There are platforms in which just reading the content of an uninitialized variable may crash ("trap representations": for example hardware with dedicated registers for pointers in which just placing an invalid address in a register - not doing anything with it - provokes an hardware exception).
No, it is not possible to allocate an array with new[] and specify an initial value for the array elements. You have to fill in the array after the allocation is finished, eg:
int count = 5;
int* a = new int[count];
for (int i = 0; i < count; ++i)
a[i] = 10;
...
delete[] a;
That is not very C++-ish. You could use std::fill() to get rid of the loop, at least:
int count = 5;
int* a = new int[count];
std::fill(a, a+count, 10);
...
delete[] a;
A better option is to switch to a std::vector instead, which has a constructor that does exactly what you are looking for:
std::vector<int> a(5, 10); // create 5 elements initialized to value 10
std::vector has a constructor where you can specify the initial size and initial value:
std::vector<int> an_array(size, init_value);
If you want to use a dynamic array using new[], you have to assign the initial value to each element:
int* array = new a[size];
for(int i = 0; i < size; ++i)
array[i] = init_value;
...
delete[] array;
Use std::array if the size is known at compile-time:
std::array<int, 5> myArray = { 1, 2, 3, 4, 5 };
Which is RAII-conform and safe.
You just have to include <array> and <initializer_list>.
In other cases, use std::vector.
This works for me with g++ 4.8.2.
#include <iostream>
int main()
{
int* a = new int[5]{10, 10, 10, 10, 10};
for ( int i = 0; i < 5; ++i )
{
std::cout << a[i] << " ";
}
std::cout << std::endl;
}
Output:
10 10 10 10 10
Update, in response to OP's comment
When you use
std::vector<int> v(5, 10);
the constructor of std::vector used is:
vector( size_type count,
const T& value,
const Allocator& alloc = Allocator());
Let's say you have a class
class MyClass
{
public:
MyClass(int ) {}
};
You can construct a std::vector<MyClass> using:
std::vector<MyClass> v(10, MyClass(50));
or
std::vector<MyClass> v(10, 50);
In the second case, the compiler knows how to implicitly construct a temporary MyClass object given the argument 50 alone. But either way, a temporary MyClass object is being passed to the vector, and that is OK because the argument type of that parameter is const MyClass&, which can bind to a temporary object.