Initializer list for dynamic arrays? - c++

It is possible to give an initializer list to the definition of a static array. Example:
int main()
{
int int_static[2] = {1,2};
}
Is a similar initializer list possible for a dynamic array?
int main()
{
int* int_ptr = new int[2];
}
This is closer to what I am trying to do:
struct foo
{
foo(){}
foo(void * ptr): ptr_(ptr) {}
void * ptr_;
};
int main()
{
foo* foo_ptr = new foo[10];
}
At initialization time not the default constructor should be called, but foo:foo(void*).
The point of having a static initializer list for a dynamic array might come handy in the case of Just-In-Time compilation for accelerator cores which do have only a limited amount of stack available, but at the same time you construct your objects with a (accelerator compile time = host run time) static initializer list.
I assume not (since this would require the compiler to generate additional code, namely to copy the values of the arguments to the heap location). I think c++0x supports some of this, but I cannot use it.
Right now I could use such a construct. Maybe someone knows a trick..
Best!

At the time the OP posted this question, C++11 support may not have been very prevalent yet, which is why the accepted answer says this is not possible. However, initializing a dynamic array with an explicit initializer list should now be supported in all major C++ compilers.
The syntax new int[3] {1, 2, 3} was standardized in C++11. Quoting the new expression page on cppreference.com:
The object created by a new-expression is initialized according to the following rules:
...
If type is an array type, an array of objects is initialized:
...
If initializer is a brace-enclosed list of arguments, the array is aggregate-initialized. (since C++11)
So, given the OP's example, the following is perfectly legal when using C++11 or newer:
foo * foo_array = new foo[2] { nullptr, nullptr };
Note that by providing pointers in the initializer list, we're actually coaxing the compiler to apply the foo(void * ptr) constructor (rather than the default constructor), which was the desired behavior.

No, you cannot do that.
I think C++ doesn't allow this because allowing such thing doesn't add any nice-to-have feature to the language. In other words, what would be the point of dynamic array if you use a static initializer to initialize it?
The point of dynamic array is to create an array of size N which is known at runtime, depending on the actual need. That is, the code
int *p = new int[2];
makes less sense to me than the following:
int *p = new int[N]; //N is known at runtime
If that is so, then how can you provide the number of elements in the static initializer because N isn't known until runtime?
Lets assume that you're allowed to write this:
int *p = new int[2] {10,20}; //pretend this!
But what big advantage are you getting by writing this? Nothing. Its almost same as:
int a[] = {10,20};
The real advantage would be when you're allowed to write that for arrays of N elements. But then the problem is this:
int *p = new int[N] {10,20, ... /*Oops, no idea how far we can go? N is not known!*/ };

No, you will have to create the elements dynamically.
Alternatively, you can use a local array and copy its elements over those of the dynamically allocated array:
int main() {
int _detail[] = { 1, 2 };
int * ptr = new int[2];
std::copy( _detail, _detail+(sizeof detail / sizeof *detail), ptr );
delete [] ptr;
}
In the limited version of setting all elements to 0, you can use an extra pair of parenthesis in the new call:
int * ptr = new int[2](); // will value initialize all elements
But you seem to be looking for a different thing.

Given that you're real class is more complex than an int, and constructed from differing values, it's complicated.
A vector can be constructed with iterators if you have an existing array/vector with the correct values to default from, or you have to use placement new.
//vector
int main()
{
int int_static[2] = {1,2};
std::vector<int> int_dynamic(int_static, int_static+2);
//this is what everyone else is saying. For good reason.
}
//placement new
int function_that_returns_constructed_from_values() {
return rand();
}
int main()
{
int count = 2;
char *char_dynamic = new char[count * sizeof(int)];
int *int_dynamic = char_dynamic;
for(int i=0; i<count; ++i)
new(int_dynamic+i)int(function_that_returns_constructed_from_values());
//stuff
for(int i=0; i<count; ++i)
(int_dynamic+i)->~int(); //obviously not really int
delete []char_dynamic;
}
Obviously, the vector is the preferred way to do this.

The initializer data must be somewhere anyway. Simply name it.
E.g.,
#include <stddef.h>
#include <algorithm> // std::copy
#include <vector>
typedef ptrdiff_t Size;
template< class Type, Size n >
Size countOf( Type (&)[n] ) { return n; }
int main()
{
using namespace std;
static int const initData[] = {1,2};
static Size const n = countOf( initData );
// Initialization of a dynamically allocated array:
int* pArray = new int[n];
copy( initData, initData + n, pArray );
// Initialization of a vector:
vector<int> v( initData, initData + n );
}
EDIT: fixed a thinko in above code. I hastened to add example on request. So what I put did erroneously use return value from std::copy.
Cheers & hth.,

Related

SFML returning Vertex array [duplicate]

I am fairly new to C++ and have been avoiding pointers. From what I've read online I cannot return an array but I can return a pointer to it. I made a small code to test it and was wondering if this was the normal / correct way to do this:
#include <iostream>
using namespace std;
int* test (int in[5]) {
int* out = in;
return out;
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int* pArr = test(arr);
for (int i = 0; i < 5; i++) cout<<pArr[i]<<endl;
cout<<endl;
return 0;
}
Edit: This seems to be no good. How should I rewrite it?
int* test (int a[5], int b[5]) {
int c[5];
for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
int* out = c;
return out;
}
Your code as it stands is correct but I am having a hard time figuring out how it could/would be used in a real world scenario. With that said, please be aware of a few caveats when returning pointers from functions:
When you create an array with syntax int arr[5];, it's allocated on the stack and is local to the function.
C++ allows you to return a pointer to this array, but it is undefined behavior to use the memory pointed to by this pointer outside of its local scope. Read this great answer using a real world analogy to get a much clear understanding than what I could ever explain.
You can still use the array outside the scope if you can guarantee that memory of the array has not be purged. In your case this is true when you pass arr to test().
If you want to pass around pointers to a dynamically allocated array without worrying about memory leaks, you should do some reading on std::unique_ptr/std::shared_ptr<>.
Edit - to answer the use-case of matrix multiplication
You have two options. The naive way is to use std::unique_ptr/std::shared_ptr<>. The Modern C++ way is to have a Matrix class where you overload operator * and you absolutely must use the new rvalue references if you want to avoid copying the result of the multiplication to get it out of the function. In addition to having your copy constructor, operator = and destructor, you also need to have move constructor and move assignment operator. Go through the questions and answers of this search to gain more insight on how to achieve this.
Edit 2 - answer to appended question
int* test (int a[5], int b[5]) {
int *c = new int[5];
for (int i = 0; i < 5; i++)
c[i] = a[i]+b[i];
return c;
}
If you are using this as int *res = test(a,b);, then sometime later in your code, you should call delete []res to free the memory allocated in the test() function. You see now the problem is it is extremely hard to manually keep track of when to make the call to delete. Hence the approaches on how to deal with it where outlined in the answer.
Your code is OK. Note though that if you return a pointer to an array, and that array goes out of scope, you should not use that pointer anymore. Example:
int* test (void)
{
int out[5];
return out;
}
The above will never work, because out does not exist anymore when test() returns. The returned pointer must not be used anymore. If you do use it, you will be reading/writing to memory you shouldn't.
In your original code, the arr array goes out of scope when main() returns. Obviously that's no problem, since returning from main() also means that your program is terminating.
If you want something that will stick around and cannot go out of scope, you should allocate it with new:
int* test (void)
{
int* out = new int[5];
return out;
}
The returned pointer will always be valid. Remember do delete it again when you're done with it though, using delete[]:
int* array = test();
// ...
// Done with the array.
delete[] array;
Deleting it is the only way to reclaim the memory it uses.
New answer to new question:
You cannot return pointer to automatic variable (int c[5]) from the function. Automatic variable ends its lifetime with return enclosing block (function in this case) - so you are returning pointer to not existing array.
Either make your variable dynamic:
int* test (int a[5], int b[5]) {
int* c = new int[5];
for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
return c;
}
Or change your implementation to use std::array:
std::array<int,5> test (const std::array<int,5>& a, const std::array<int,5>& b)
{
  std::array<int,5> c;
  for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
  return c;
}
In case your compiler does not provide std::array you can replace it with simple struct containing an array:
struct array_int_5 {
int data[5];
int& operator [](int i) { return data[i]; }
int operator const [](int i) { return data[i]; }
};
Old answer to old question:
Your code is correct, and ... hmm, well, ... useless. Since arrays can be assigned to pointers without extra function (note that you are already using this in your function):
int arr[5] = {1, 2, 3, 4, 5};
//int* pArr = test(arr);
int* pArr = arr;
Morever signature of your function:
int* test (int in[5])
Is equivalent to:
int* test (int* in)
So you see it makes no sense.
However this signature takes an array, not pointer:
int* test (int (&in)[5])
A variable referencing an array is basically a pointer to its first element, so yes, you can legitimately return a pointer to an array, because thery're essentially the same thing. Check this out yourself:
#include <assert.h>
int main() {
int a[] = {1, 2, 3, 4, 5};
int* pArr = a;
int* pFirstElem = &(a[0]);
assert(a == pArr);
assert(a == pFirstElem);
return 0;
}
This also means that passing an array to a function should be done via pointer (and not via int in[5]), and possibly along with the length of the array:
int* test(int* in, int len) {
int* out = in;
return out;
}
That said, you're right that using pointers (without fully understanding them) is pretty dangerous. For example, referencing an array that was allocated on the stack and went out of scope yields undefined behavior:
#include <iostream>
using namespace std;
int main() {
int* pArr = 0;
{
int a[] = {1, 2, 3, 4, 5};
pArr = a; // or test(a) if you wish
}
// a[] went out of scope here, but pArr holds a pointer to it
// all bets are off, this can output "1", output 1st chapter
// of "Romeo and Juliet", crash the program or destroy the
// universe
cout << pArr[0] << endl; // WRONG!
return 0;
}
So if you don't feel competent enough, just use std::vector.
[answer to the updated question]
The correct way to write your test function is either this:
void test(int* a, int* b, int* c, int len) {
for (int i = 0; i < len; ++i) c[i] = a[i] + b[i];
}
...
int main() {
int a[5] = {...}, b[5] = {...}, c[5] = {};
test(a, b, c, 5);
// c now holds the result
}
Or this (using std::vector):
#include <vector>
vector<int> test(const vector<int>& a, const vector<int>& b) {
vector<int> result(a.size());
for (int i = 0; i < a.size(); ++i) {
result[i] = a[i] + b[i];
}
return result; // copy will be elided
}
In a real app, the way you returned the array is called using an out parameter. Of course you don't actually have to return a pointer to the array, because the caller already has it, you just need to fill in the array. It's also common to pass another argument specifying the size of the array so as to not overflow it.
Using an out parameter has the disadvantage that the caller may not know how large the array needs to be to store the result. In that case, you can return a std::vector or similar array class instance.
Your code (which looks ok) doesn't return a pointer to an array. It returns a pointer to the first element of an array.
In fact that's usually what you want to do. Most manipulation of arrays are done via pointers to individual elements, not via pointers to the array as a whole.
You can define a pointer to an array, for example this:
double (*p)[42];
defines p as a pointer to a 42-element array of doubles. A big problem with that is that you have to specify the number of elements in the array as part of the type -- and that number has to be a compile-time constant. Most programs that deal with arrays need to deal with arrays of varying sizes; a given array's size won't vary after it's been created, but its initial size isn't necessarily known at compile time, and different array objects can have different sizes.
A pointer to the first element of an array lets you use either pointer arithmetic or the indexing operator [] to traverse the elements of the array. But the pointer doesn't tell you how many elements the array has; you generally have to keep track of that yourself.
If a function needs to create an array and return a pointer to its first element, you have to manage the storage for that array yourself, in one of several ways. You can have the caller pass in a pointer to (the first element of) an array object, probably along with another argument specifying its size -- which means the caller has to know how big the array needs to be. Or the function can return a pointer to (the first element of) a static array defined inside the function -- which means the size of the array is fixed, and the same array will be clobbered by a second call to the function. Or the function can allocate the array on the heap -- which makes the caller responsible for deallocating it later.
Everything I've written so far is common to C and C++, and in fact it's much more in the style of C than C++. Section 6 of the comp.lang.c FAQ discusses the behavior of arrays and pointers in C.
But if you're writing in C++, you're probably better off using C++ idioms. For example, the C++ standard library provides a number of headers defining container classes such as <vector> and <array>, which will take care of most of this stuff for you. Unless you have a particular reason to use raw arrays and pointers, you're probably better off just using C++ containers instead.
EDIT : I think you edited your question as I was typing this answer. The new code at the end of your question is, as you observer, no good; it returns a pointer to an object that ceases to exist as soon as the function returns. I think I've covered the alternatives.
you can (sort of) return an array
instead of
int m1[5] = {1, 2, 3, 4, 5};
int m2[5] = {6, 7, 8, 9, 10};
int* m3 = test(m1, m2);
write
struct mystruct
{
int arr[5];
};
int m1[5] = {1, 2, 3, 4, 5};
int m2[5] = {6, 7, 8, 9, 10};
mystruct m3 = test(m1,m2);
where test looks like
struct mystruct test(int m1[5], int m2[5])
{
struct mystruct s;
for (int i = 0; i < 5; ++i ) s.arr[i]=m1[i]+m2[i];
return s;
}
not very efficient since one is copying it delivers a copy of the array

Initializing a dynamic array

I'm working with a dynamic array of a given class, let's call it 'MyClass', the thing is this class has a specialized constructor with a given parameter.
As far as I know to initialize a dynamic array I should use this:
MyClass *myArray = new MyClass[]();
Is there a way to initialize my array using my specialized constructor? something like:
MyClass *myArray = new MyClass[](givenParameter);
and this got me to another question, what does the line MyClass *myArray = new MyClass[](); is it calling a base constructor without any given parameters or does it do something else internally?
It may be something obvious but I wasn't able to find much information on this, at least not something to solve my first question. Thank you, everyone.
The syntax MyClass *myArray = new MyClass[size](); allows you to value-initialize the elements when they are trivial simple types (like integers, etc, thus setting them to 0), but it is not very meaningful for elements of class/struct types, so the () is usually omitted for those types. new[] can only call default constructors on class/struct types, it does not allow you to call non-default constructors.
However, a way to handle that is to use placement-new instead, which would then allow you to construct each MyClass object individually, even with different parameter values if needed.
// allocate raw memory to hold the objects array...
char *myArrayBuf = new char[sizeof(MyClass) * NumberOfItems];
/* alternatively, in C++11 and later:
#include <type_traits>
using element_type = std::aligned_storage<sizeof(MyClass), alignof(MyClass)>::type;
element_type *myArrayBuf = new element_type[NumberOfItems];
*/
// call the constructor on each object in the array...
MyClass *myArray = reinterpret_cast<MyClass*>(myArrayBuf);
for(int i = 0; i < NumberOfItems; ++i) {
new(&myArray[i]) MyClass(givenParameter);
}
// use myArray as needed ...
// call the destructor on each object in the array...
for(int i = 0; i < NumberOfItems; ++i) {
myArray[i].~MyClass();
}
// deallocate the raw memory for the array...
delete[] myArrayBuf;
In C++11 and later, this would be easier to handle using a std::vector instead (which you should be using anyway):
#include <vector>
std::vector<MyClass> myArray;
myArray.reserve(NumberOfItems);
for(int i = 0; i < NumberOfItems; ++i) {
myArray.emplace_back(givenParameter);
}
// use myArray as needed ...
Prior to C++11, you can still use std::vector, but it would require copy-constructing the array elements:
#include <vector>
std::vector<MyClass> myArray;
myArray.reserve(NumberOfItems);
for(int i = 0; i < NumberOfItems; ++i) {
myArray.push_back(MyClass(givenParameter));
}
// use myArray as needed ...
MyClass *arr;
arr = new MyClass[2]{{10, "hello"},{20, "custom constructor"}};
I'm not sure there's another way to initialize C-array with non-standard constructor.
But if you're ok with using std::vector then:
#include <vector>
size_t size = 2;
std::vector<MyClass> myArray(size, MyClass(givenParameter));

Is new int[][] a valid thing to do in C++?

I have come across some code which allocates a 2d array with following approach:
auto a = new int[10][10];
Is this a valid thing to do in C++? I have search through several C++ reference books, none of them has mentioned such approach.
Normally I would have done the allocation manually as follow:
int **a = new int *[10];
for (int i = 0; i < 10; i++) {
a[i] = new int[10];
}
If the first approach is valid, then which one is preferred?
The first example:
auto a = new int[10][10];
That allocates a multidimensional array or array of arrays as a contiguous block of memory.
The second example:
int** a = new int*[10];
for (int i = 0; i < 10; i++) {
a[i] = new int[10];
}
That is not a true multidimensional array. It is, in fact, an array of pointers and requires two indirections to access each element.
The expression new int[10][10] means to allocate an array of ten elements of type int[10], so yes, it is a valid thing to do.
The type of the pointer returned by new is int(*)[10]; one could declare a variable of such a type via int (*ptr)[10];.
For the sake of legibility, one probably shouldn't use that syntax, and should prefer to use auto as in your example, or use a typedef to simplify as in
using int10 = int[10]; // typedef int int10[10];
int10 *ptr;
In this case, for small arrays, it is more efficient to allocate them on the stack. Perhaps even using a convenience wrapper such as std::array<std::array<int, 10>, 10>. However, in general, it is valid to do something like the following:
auto arr = new int[a][b];
Where a is a std::size_t and b is a constexpr std::size_t. This results in more efficient allocation as there should only be one call to operator new[] with sizeof(int) * a * b as the argument, instead of the a calls to operator new[] with sizeof(int) * b as the argument. As stated by Galik in his answer, there is also the potential for faster access times, due to increased cache coherency (the entire array is contiguous in memory).
However, the only reason I can imagine one using something like this would be with a compile-time-sized matrix/tensor, where all of the dimensions are known at compile time, but it allocates on the heap if it exceeds the stack size.
In general, it is probably best to write your own RAII wrapper class like follows (you would also need to add various accessors for height/width, along with implementing a copy/move constructor and assignment, but the general idea is here:
template <typename T>
class Matrix {
public:
Matrix( std::size_t height, std::size_t width ) : m_height( height ), m_width( width )
{
m_data = new T[height * width]();
}
~Matrix() { delete m_data; m_data = nullptr; }
public:
T& operator()( std::size_t x, std::size_t y )
{
// Add bounds-checking here depending on your use-case
// by throwing a std::out_of_range if x/y are outside
// of the valid domain.
return m_data[x + y * m_width];
}
const T& operator()( std::size_t x, std::size_t y ) const
{
return m_data[x + y * m_width];
}
private:
std::size_t m_height;
std::size_t m_width;
T* m_data;
};

How can I give values for a newly initialized array right after declaration

How can I give values of my new initialized array if I am using a pointer? E.g.
int* array = new int[3]; <- I want to give the values {1,2,3} on the same row but not:
array[0] = 5;
array[1] = 3;
array[2] = 4;
You can use a brace enclosed initializer:
int* array = new int[3]{1, 2, 3};
The usual warning is that you would need to ensure that you call delete [] on array. This is harder to guarantee than apears at first sight. For this and other reasons, it may be a better idea to use an std::vector<int>:
std::vector<int> v{1,2,3};
If you are stuck with an older, pre-C++11 implementation, then you cannot use the brace enclosed initializer syntax. You will have to use a loop at some level (whether your own, or by using some standard or 3rd party library function.)
If you absolutely, positively have to use C++98, you could do something like this:
#include <algorithm> //copy
#include <iostream> // cout
#include <iterator> // iostream_iterator
void foo()
{
int init[] = { 1, 2, 3 };
int* array = new int[3];
std::copy(init, init + 3, array);
std::copy(array, array + 3, std::ostream_iterator<int>(std::cout, ", "));
// better hope nothing bad like an exception happens in between
delete[] array;
}
int main()
{
foo();
}
Live Example. So you define a C-array of initializers and copy them into your dynamically allocated array. The C-array init will be automatically deleted when foo() exits, but you have to manually delete array. The recommended way is to use std::vector in C++11 with an initializer-list.

How to solve the error "expression must be a modifiable lvalue" in c++?

const int ADJ_MATRIX[VERTEX_NUM][VERTEX_NUM]={
{0,1,1,0,0,0,0,0},
{1,0,0,1,1,0,0,0},
{1,0,0,0,0,1,1,0},
{0,1,0,0,0,0,0,1},
{0,1,0,0,0,0,0,1},
{0,0,1,0,0,0,1,0},
{0,0,1,0,0,1,0,0},
{0,0,0,1,1,0,0,0}
};
typedef struct {
int vertex;
int matrix[VERTEX_NUM][VERTEX_NUM];
int vNum;
int eNum;
}Graph;
void buildGraph(Graph *graph){
graph->vNum = VERTEX_NUM;
graph->eNum = EDGE_NUM;
graph->matrix = ADJ_MATRIX;
}
The error occurs in this sentence:
graph->matrix = ADJ_MATRIX;
I am new to c++. please tell me why this problem occur and how to solve it?
I want to assign ADJ_MATRIX to the matrix in struct.
As was said, you can't assign arrays in C++. This is due to the compiler being a meanie, because the compiler can. It just won't let you do it...
... unless you trick it ;)
template <typename T, int N>
struct square_matrix {
T data[N][N];
};
square_matrix<int, 10> a;
square_matrix<int, 10> b;
a = b; // fine, and actually assigns the .data arrays
a.data = b.data; // not allowed, compiler won't let you assign arrays
The catch? Now the code needs some little things:
const square_matrix<int, VERTEX_NUM> ADJ_MATRIX={{
// blah blah
}}; // extra set of braces
typedef struct {
int vertex;
square_matrix<int, VERTEX_NUM> matrix;
int vNum;
int eNum;
}Graph;
void buildGraph(Graph *graph){
graph->vNum = VERTEX_NUM;
graph->eNum = EDGE_NUM;
graph->matrix = ADJ_MATRIX; // no change
}
And to access the cells, now we need to use graph->matrix.data[1][2]. This can be mitigated by overloading operator[] or operator() for square_matrix. However, this is now getting terribly close to the new std::array class, or the Boost equivalent boost::array, so it might be wise to consider those instead.
Unfortunately (or maybe fortunately, who knows...) you can't just assign one array to another in C++.
If you want to copy an array, you will need to either copy each of it's elements into a new array one by one, or use the memcpy() function:
for( int i = 0; i < VERTEX_NUM; i++ )
for( int j = 0; j < VERTEX_NUM; j++ )
graph->matrix[i][j] = ADJ_MATRIX[i][j];
or
memcpy( graph->matrix, ADJ_MATRIX, VERTEX_NUM * VERTEX_NUM * sizeof(int) );
Arrays are not assignable. You can use memcpy:
memcpy(graph->matrix, ADJ_MATRIX, sizeof(graph->matrix));
You cannot assign an array to another array. You will need to copy the elements from the source to the destination index by index, or use memcpy to copy the data. Array assignment like this is not allowed
You are trying to assign your variable address of a constant data,
try using
memcpy(graph->matrix,ADJ_MATRIX,sizeof(ADJ_MATRIX));//using sizeof(graph->matrix) is safer.
You can't use an array in assignments. You may use cycles or memcpy instead
memcpy(graph->matrix, ADJ_MATRIX, VERTEX_NUM * VERTEX_NUM * sizeof(int));
or
for(int i = 0; i < VERTEX_NUM; ++i){
for(int j = 0; j < VERTEX_NUM; ++j){
graph->matrix[i][j] = ADJ_MATRIX[i][j];
}
}
The error is thrown, because int matrix[VERTEX_NUM][VERTEX_NUM] in a structure definition means that each structure will have a 2D array of integers of the predefined size and matrix is going to be pointing to its first element. The thing is that matrix cannot be assigned to an arbitrary address, because it's a const pointer i.e. its value (the address it's pointing to) cannot change.
You have 2 options here: you can either use memcpy or some stl algorithms to copy the ADJ_MATRIX into matrix directly or you can declare matrix as a pointer and do the assignment that is currently produces an error.
The latter can be done in the following way:
typedef struct {
int vertex;
const int (*matrix)[VERTEX_NUM];
int vNum;
int eNum;
}Graph;
Thus you can do graph->matrix = ADJ_MATRIX assignment, but you won't be able to modify the individual items in matrix due to constness. This means, graph->matrix[0][1] = 3; is not allowed, while you can read the elements freely.