How come I can do this:
char a[] = {1, 2};
char b[] = {3, 4, 5};
const char *r[] = {
a, b
};
But I can't do it this way:
const char *r[] = {
{1,2}, {3,4,5}
};
Is there any shortcut for initializing an array of pointers to arrays of different length?
There is no easy solution to achieve the syntax you're looking for: these pointers have to point at some arrays, and these arrays must have an adequate lifetime.
You probably want them to be automatic, which implies declaring them as local variables the way you did.
You could achieve sort of what you want with dynamic allocation, i.e:
const char *r[] = {
new char[]{1,2}, new char[]{3,4,5}
};
... in which case the arrays will have sufficient lifetime, but then you have the burden of delete[]ing them at the right time. Not really a solution.
The first form works because, when used like this, the name of each array is converted to a pointer (to its first element). Since the result of the conversion is a char * it can be stored in an array of char *.
The second form doesn't work since {1,2} and {3,4,5} are (initialisers for) arrays, and arrays are not pointers. An unnamed array (which these are) cannot be implicitly be converted to a pointer.
The first form IS the only shortcut to initialise an array of pointers, so each pointer points to the first element of an array.
You would be normally better off using standard containers (e.g. a std::vector<std::string>) and avoid the complexity of pointers (and conversions of array names to pointers) entirely.
this code doesn't work,
const char r[][] = {{1,2}, {3,4,5}};
fails with :
x86-64 gcc 5.1!!error: declaration of 'r' as multidimensional array
must have bounds for all dimensions except the first
fix it like so:
const char r[][3] = {{1,2}, {3,4,5}};
side note: it's a bad practice to use C-like arrays in c++ use std::array if you know your values at compile time.
EDIT:
you can do this ugly hack(it compiles, but I don't know how many rockets it will launch).
const char *r[] = { (const char[]){1,2}, (const char[]){1,2,3}};
you can't write:
const char *r[] = { {1,2}, {3,4,5} };
because you cannot write:
r[0] = 1, 2, 3; // but you can r[0] = "1, 2, 3";
to initialize your array of pointers to char you can:
const char *r[] = {
{"1,2"}, {"3,4,5"}};
so r is a an array of pointers to char.
Related
In C++, I can statically initialize an array, e.g.:
int a[] = { 1, 2, 3 };
Is there an easy way to initialize a dynamically-allocated array to a set of immediate values?
int *p = new int[3];
p = { 1, 2, 3 }; // syntax error
...or do I absolutely have to copy these values manually?
You can in C++0x:
int* p = new int[3] { 1, 2, 3 };
...
delete[] p;
But I like vectors better:
std::vector<int> v { 1, 2, 3 };
If you don't have a C++0x compiler, boost can help you:
#include <boost/assign/list_of.hpp>
using boost::assign::list_of;
vector<int> v = list_of(1)(2)(3);
You have to assign each element of the dynamic array explicitly (e.g. in a for or while loop)
However the syntax int *p = new int [3](); does initialize all elements to 0 (value initialization $8.5/5)
To avoid endless push_backs, I usually initialize a tr1::array and create a std::vector (or any other container std container) out of the result;
const std::tr1::array<T, 6> values = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(values.begin(), values.end());
The only annoyance here is that you have to provide the number of values explicitly.
This can of course be done without using a tr1::array aswell;
const T values[] = {T(1), T(2), T(3), T(4), T(5), T(6)};
std::vector <T> vec(&values[0], &values[sizeof(values)/sizeof(values[0])]);
Althrough you dont have to provide the number of elements explicitly, I prefer the first version.
No, you cannot initialize a dynamically created array in the same way.
Most of the time you'll find yourself using dynamic allocation in situations where static initialization doesn't really make sense anyway. Such as when you have arrays containing thousands of items. So this isn't usually a big deal.
Using helper variable:
const int p_data[] = {1, 2, 3};
int* p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
or, one line
int p_data[] = {1, 2, 3}, *p = (int*)memcpy(new int[3], p_data, sizeof(p_data));
Never heard of such thing possible, that would be nice to have.
Keep in mind that by initializing the array in the code that way
int a[] = { 1, 2, 3 };
..... only gains you easier code writing and NOT performance.
After all, the CPU will do the work of assigning values to the array, either way you do it.
I have several two dimensional arrays of various, differing lengths:
int Array_A[][2] = {{...}, {...}, {...}, ...};
int Array_B[][2] = {{...}, {...}, ...};
int Array_C[][2] = {{...}, ...};
I need another array which allows me to access these arrays:
??? Full_Array[] = {Array_A, Array_B, Array_C};
What is the correct type of ??? that I should use? I tried uint** and uint* but neither works.
If it's not doable, suppose I am not allowed to change the definition of Array_A, Array_B, ... What is a good way to define Full_Array?
Array_A, Array_B, and Array_C are all arrays of arrays of 2 ints, so they can all undergo the array-to-pointer conversion at the top level into pointer to array of 2 ints.
So Full_Array needs to be an array of pointers to arrays of 2 ints. The declaration can be written:
int (*FullArray[])[2] = {Array_A, Array_B, Array_C};
Note that there is no way to tell what the lengths of the subarrays are, unless you have sentinel values.
If the arrays Array_A, Array_B, and Array_C are of the same size, you can create pointers to them using the & operator and store them in an array. If they are of different sizes, the & operator will create different pointer types and you won't be able to store them in the pointer array.
int Array_A[3][2] = { ... };
int Array_B[3][2] = { ... };
int Array_C[3][2] = { ... };
typedef int (*PtrType)[3][2];
PtrType Full_Array[] = {&Array_A, &Array_B, &Array_C};
The following will be an error.
int Array_A[][2] = { {}, {}, {} }; // Implied dimensions [3][2]
int Array_B[][2] = { {}, {} }; // Implied dimensions [2][2]
int Array_C[][2] = { {}, {}, {} }; // Implied dimensions [3][2]
typedef int (*PtrType)[3][2];
PtrType Full_Array[] = {&Array_A, &Array_B, &Array_C};
In addition to the already posted answers, you might want to consider using decltype to automatically deduce the type:
using PtrToArrayElem =
decltype(&(Array_A[0])); // C++11, or
// std::decay_t<decltype(Array_A)>; // C++14 alternative, or
// typename std::decay<decltype(Array_A)>::type; // C++11 version of above
PtrToArrayElem arrayOfPtrsToFirstElements[] = {Array_A, Array_B, Array_C};
The benefit is that if you ever change the type of one of the arrays, then you don't need to change the code here. Just make sure to keep the rest of the code (accessing the array of pointers) generic, too.
Of course this also works if you rather want to store addresses to the arrays themselves, which will only work if they're of the same size:
using PtrToArray = decltype(&Array_A);
PtrToArray arrayOfPtrToArray[] = {&Array_A, &Array_B, &Array_C};
Note: Variable names are chosen for descriptive purposes of this answer. You should of course use meaningful names.
I have a number of existing arrays of a struct type
typedef struct Patterns
{
int a;
int b;
int c;
}
The arrays are named as follows
arr0, arr1, arr2, arr3, arr4, etc.
I am passed an integer value and would like to use it to look up the array that is needed and copy it to a temporary array.
i.e. int 0 corresponds to array arr0 and so on.
I've tried to use the "map" method but i run into the error "expression must be a modifiable lvalue" when assigning the arrays to the integer keys
std::map<int, Patterns[]>map1;
map1[0] = arr0;
map1[1] = arr1;
What am I doing wrong? Is there an easier way to quickly look up which array i need to utilize?
use vector not array. You cant really create a map of pattern[].
You should have
vector<vector<Pattern>> arrays;
arrays[0] = arr0;
arrays[1] = arr1;
etc.
How would you use array methods such as .size() and .empty() in a function if you can only pass pointers to the array, since pointers just point to the first element?
I'm specifically asking about using array methods and not about finding ways to check the array size or whether the array is empty.
For example, how would you get array.empty() in the code below to work?
class Solution{
public:
void testArray(int &array)[5]){ //or (int* array) or (int array[])
std::cout << array.empty() << std::endl;
}
}
int main(int argc, const char * argv[])
{
int a1[] = {1,2,3,4,5};
Solution s1;
s1.testArray(a1);
}
You are confusing the type int[5] with std::array<int, 5>. These are different things.
The first type (a "bare" array) has no members and can decay into a pointer-to-int automatically, which does indeed point to the first element and conveys no information about the array's length.
std::array is a template class that provides bounds-checking (using std::array::at()) and other standard STL container methods on top of a bare array.
Replace int a1[] = {1,2,3,4,5}; with std::array<int, 5> a1 = {{1,2,3,4,5}}; (and update the signature of Solution::testArray() to take a std::array<int, 5> const & parameter) and you will be able to use these methods.
I have a variable in class declared as compile-time constant with known size:
static const int array[5][5]; // constants initlialised in another place
And a function that returns it virtually:
virtual const int** getArray() { return array; }
How to get this array with this method, and cast it to fixed-size array, not pointers-based, so I can use it like cout << data[2][2] ?
Sample that dosn't compile:
const int[5][5] data = object->getArray();
cout << data[2][2];
Sample that compiles but crashes application:
const int** data = object->getArray();
cout << data[2][2];
Note: one solution is to create typedef arr[5] and declare methods with arr* but i don't want to create a typedef for each compile-time size wich I use like typedef arr5[5]; typedef arr10[10] etc. I'm looking for something more like:
const int(*)[5] data = object->getArray(); // won't compile, example only
Let's assume that compile-time constant array is loaded with dynamic DLL and is already in memory, is it possible to use this data as array without allocating new memory and populating it from compile-time constants?
virtual const int** getArray() { return array; }
That won't work, and shouldn't compile; you're trying to return a pointer to some pointers, but there are no pointers to point to, only an array of arrays.
You can return a pointer to those arrays, preserving the type:
virtual const int (*getArray())[5] { return array; }
const int (*data)[5] = getArray();
cout << data[2][2];
In C++11, it might be nicer to wrap the arrays up in std::array, and return a reference to that, to avoid some of the nasty syntax.
Use std::array:
#include <array>
static const std::array<std::array<int, 5>, 5> myarray; // constants initlialised in another place
virtual const std::array<std::array<int, 5>, 5>& getArray() const
{
return myarray;
}
If you do not have C++11 support, you can use std::tr1::array or boost::array (or roll out your own fixed size array type.)
that is not possible. You lose all size information when an array is passed to or returned from a function. The array decays into a pointer so to speak
It's simple enough, you are almost there
const int(*)[5] data = reinterpret_cast<int(*)[5]>(object->getArray());