assign elements in vector declared with new. C++ - c++

I am trying to use a large 2D vector which I want to allocate with new (because it is large).
if I say:
vector< vector<int> > bob;
bob = vector< vector<int> >(16, vector<int>(1<<12,0));
bob[5][5] = 777;
it works. But if I say:
std::vector< std::vector<int> > *mary;
mary = new vector< vector<int> >(16, vector<int>(1<<12, 0));
mary[5][5] = 777;
it doesn't work and I get the error:
Error 1 error C2679: binary '=' : no operator found which takes a right-hand operand of type 'int' (or there is no acceptable conversion) c:\Users\jsparger\Documents\My Dropbox\ARI\VME_0.01\VME_0.01\V965.cpp 11 VME_0.01
Obviously I am new to C++. Could someone explain what syntax I need to use to perform this operation. mary is a pointer, so I can see why this wouldn't work, but *mary[5][5] = whatever is not allowed either because of "new", right?
Thanks for the help. This vector is what I will be using for now because it seems easy enough for my small c++ brain to understand, but feel free to let me know if a large vector like this is a bad idea, etc.
Thanks a bunch.
Edit:
I am mistaken about the "not allowed because of new". I don't know where I misread that, because it obviously works, and wouldn't make too much sense for it not to. Thanks.

If mary is a pointer then you have to dereference it before applying the subscript operator:
(*mary)[5][5] = 777;
The parentheses are required because the subscript has higher precedence than the dereference.

Vectors store their elements on the heap, anyway. There's no point in allocating the vector object itself on the heap, since it is very small (typically 12 bytes on a 32-bit machine).

In plain C, arrays and pointers are similar (not the same!), which leads to your confusion. In plain C, if you have the following declarations:
int array1[100];
int *array2 = (int *)malloc(100*sizeof(int));
you can use array1 and array2 in exactly the same way.
However, if you write this in C:
int (*array3)[100];
This is something completely different. Array3 is now a pointer to an array, not a pointer to the elements of the array anymore, and if you want to access an element, you have to write this:
(*array3)[5] = 123;
In C++, you are actually doing something similar, the second 'mary' is a pointer to the vector, not a pointer to the elements in the vector. Therefore, you have to write this:
(*mary)[5][5] = 777;

Related

How to properly work with dynamically-allocated multi-dimensional arrays in C++ [duplicate]

This question already has answers here:
How do I declare a 2d array in C++ using new?
(29 answers)
Closed 7 years ago.
How do I define a dynamic multi-dimensional array in C++? For example, two-dimensional array? I tried using a pointer to pointer, but somehow it is failing.
The first thing one should realize that there is no multi-dimensional array support in C++, either as a language feature or standard library. So anything we can do within that is some emulation of it. How can we emulate, say, 2-dimensional array of integers? Here are different options, from the least suitable to the most suitable.
Improper attempt #1. Use pointer to pointer
If an array is emulated with pointer to the type, surely two-dimensional array should be emulated with a pointer to pointer to the type? Something like this?
int** dd_array = new int[x][y];
That's a compiler error right away. There is no new [][] operator, so compiler gladly refuses. Alright, how about that?
int** dd_array = new int*[x];
dd_array[0][0] = 42;
That compiles. When being executed, it crashes with unpleasant messages. Something went wrong, but what? Of course! We did allocate the memory for the first pointer - it now points to a memory block which holds x pointers to int. But we never initialized those pointers! Let's try it again.
int** dd_array = new int*[x];
for (std::size_t i = 0; i < x; ++i)
dd_array[i] = new int[y];
dd_array[0][0] = 42;
That doesn't give any compilation errors, and program doesn't crash when being executed. Mission accomplished? Not so fast. Remember, every time we did call a new, we must call a delete. So, here you go:
for (std::size_t i = 0; i < x; ++i)
delete dd_array[i];
delete dd_array;
Now, that's just terrible. Syntax is ugly, and manual management of all those pointers... Nah. Let's drop it all over and do something better.
Less improper attempt #2. Use std::vector of std::vector
Ok. We know that in C++ we should not really use manual memory management, and there is a handy std::vector lying around here. So, may be we can do this?
std::vector<std::vector<int> > dd_array;
That's not enough, obviously - we never specified the size of those arrays. So, we need something like that:
std::vector<std::vector<int> > dd_array(x);
for(auto&& inner : dd_array)
inner.resize(y);
dd_array[0][0] = 42;
So, is it good now? Not so much. Firstly, we still have this loop, and it is a sore to the eye. What is even more important, we are seriously hurting performance of our application. Since each individual inner vector is independently allocated, a loop like this:
int sum = 0;
for (auto&& inner : dd_array)
for (auto&& data : inner)
sum += data;
will cause iteration over many independently allocated inner vectors. And since CPU will only cache continuous memory, those small independent vectors cann't be cached altogether. It hurts performance when you can't cache!
So, how do we do it right?
Proper attempt #3 - single-dimensional!
We simply don't! When situation calls for 2-dimensional vector, we just programmatically use single-dimensional vector and access it's elements with offsets! This is how we do it:
vector<int> dd_array(x * y);
dd_array[k * x + j] = 42; // equilavent of 2d dd_array[k][j]
This gives us wonderful syntax, performance and all the glory. To make our life slightly better, we can even build an adaptor on top of a single-dimensional vector - but that's left for the homework.

Dynamic arrays of objects/classes in C++

I'll cut to the chase to save you all some boredom of surplus reading:
I've tried to comb the internet in search of tutorials over dynamical arrays of objects/classes where they explain how pointers are implemented here.
This in particular: TheClass **foo[10]; or something like that, I don't understand what two stars/asterisks are good for and how they are used.
And this whole thing in general.
I do know how dynamical arrays are declared,how regular pointers are used,how to make classes,how to make dynamic arrays of classes.
But all this combined got me confused.
So my questions are:
What does this do and how does it work?
Can you recommend a site where you know examples/tutorials of this can be found?
Does this have a specific name rather than "dynamic object arrays with double pointers"
or whatnot?
If no tutorial comes to mind, I'd appreciate it if you could make a very, very brief example.
Like for instance
int *something;
int somethingElse = 10;
something = &somethingElse; /*Now when you change "somethingElse","something"
will also change to the same number*/
A little super-short example and explanation like that would be greatly appreciated. =)
The simplest, more or less usefull, example using pointers to pointers would be a two dimensional array. So for example
//Create a pointer to (an array of) pointers to (an array of) ints
int** array2D;
//Create a array of pointers to (an array of) ints and assign it to the pointer
array2D = new int*[10];
//Assign each of the pointers to a new array of 10 ints
for(size_t i =0; i<10;i++) {
array2D[i] = new int[10];
}
//Now you have an 2 dimensional array of ints that can be access by
array2D[1][3] = 15;
int test = array2D[1][3];
I hope this explains a bit what pointers to pointers are and how they work.
A pointer is, well, a pointer. It points at something. Period. If you understand that much, then you should be able to understand what a pointer to a pointer is. It is just a pointer whose value is the memory address of another variable that is itself a pointer to something else. That's all. Every time you add a * to the mix, it is just another level of pointer indirection. For example:
int i;
int* p_i = &i; // p_i is a pointer to an int and points at i
int** pp_i = &p_i; // pp_i is a pointer to an int* and points at p_i
int*** ppp_i = &pp_i; // ppp_i is a pointer to an int** and points at pp_i
Now apply that concept to TheClass **foo[10]; (which is actually TheClass** foo[10]; from the compiler's perspective). It is declaring an array named foo that contains 10 TheClass** pointer-to-pointer elements. Each TheClass* might be a pointer to a specific TheClass object, or it might be a dynamic array of TheClass elements (no way to know without more context), then each TheClass** is a pointer to a particular TheClass* pointer.
Well i see you aim for the complete answer, i'll give u a brief example on that.
If you define an array of pointers to pointers, like in your "class foo**[10]" example, let's say:
int numX = 100;
int numY = 1000;
Node **some[10];
some[0] = new Node*[numX];
some[0][0] = new Node[numY];
Then what it does mean is:
You have 10 Node** in your 1st level. So you have 10 pointers to type Node**, but they aren't pointing anywhere useful yet.
This is just 10 adjacent memory locations for storing pointers. In this case it is irrelevant what they are pointing to, mainly it is just 10 fields containing space for a pointer.
Then take the first of these 10 "spaces" and assign the address of an array of 100 pointers to type Node*
some[0] = new Node*[numX]; //numX = 100
This is done and evaluated during runtime, so u can use a variable value given by user input or some application logic, to define dimensions of arrays aka memory-fields.
Now you have 1 of 10 pointers pointing to 100 pointers to type Node*, but still pointing to a black hole.
In the last step create 1000 objects of type Node and attach their addresses to the first of your 100 pointers.
some[0][0] = new Node[numY]; //numY = 1000
In the above example this means, only [0][0][0] to [0][0][999] are objects, the 1000 you created with:
This way you can build multi-dimensional arrays with the specified type. What makes the whole thing work, is that you instantiate what you need in the last dimension (3) and create pointers to uniquely index every field created from [0][0][0] to [9][99][999].
some[0][1]; // memory violation not defined
some[0][0]; // good -> points to a *Node
some[0][0][0]; // good -> actually points to Node (data)
some[1][0][0]; // memory violation not defined
As far as i know, most often you use a one-dimensional array and some tiny math, to simulate two-dimensional arrays. Like saying element [x][y] = [x+y*width];
However you want to use your memory, in the end it all boils down to some memory-adresses and their content.
TheClass** foo[10];
This line of code tells the compiler to a make an array called foo of 10 elements of type pointer to (pointer to Theclass ).
In general when you want to figure out a type that involve multiple astrisks, ampersands. Read Left to Right. so we can break out the code above to something like this:
( (Theclass) * ) * foo[10]
^ ^ ^ ^ ^
5 4 3 2 1
#1 an array of 10 elements named #2 foo #3 of type pointer #4 to pointer #5 to Theclass

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

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.

How to create Array of Dynamic Arrays in C++

I am trying to learn C++ and trying to write a code for a simple hash table like following structure:
array[0][0] array[0][1] array[0][2]
key 1 value 1 value 2
array[1][0] array[1][1]
key 2 value 3
array[2][0] array[2][1] array[2][2]
key 3 value 4 value 5
means Array of Dynamic Arrays. Now, I can't understand how to define the array like that ?
Any help on this will be grateful.
If you really did need to create a dynamic array of dynamic arrays you would have to do it using the new keyword for both arrays. For example:
// an array of int pointers... each points to the start of an array
int** arrays = new int*[10];
arrays[0] = new int[99]; // populate the first element of the array of arrays
arrays[1] = new int[47]; // arrays don't have to be the same size.
Of course I highly recommend NOT doing this. You have to then remember to use delete[] on each member of arrays and on arrays itself.
Really you should use the built in std::vector type for this. It is why it is there (I voted for the other answers!).
Just as a note, this is not contiguous memory either. Also if you do want the member arrays to be the same size you could allocate their memory in a for loop.
In C++ you would use a std::vector<T> and nest two of them in order to get a 2D array.
std::vector<std::vector<my_type>> vec;
std::vector<my_type> v;
vec.push_back(v);
v.push_back(mytype);
Create a vector <vector <T> >.
For example
vector <vector <string> > array;
vector <string> temp;
temp.push_back(key1);
temp.push_back(value1);
temp.push_back(value2);
array.push_back(temp);
.
.
.
This is old, and I'm sure I'm not writing anything answer posters don't know in the back of their minds, but OP looks like he's doing an assignment for homework. My homework requires me to write out routines with out using any STL resources. In that case the only possible answer here is the first one. Homework in the beginning isn't about efficiency, it's demonstrating use of lesson material.
Unfortunately much of the time what they want you to demonstrate is never illustrated in the lessons.
Which brings OP's like this one to dig the web for hard to find reference. Hard to find because nobody really does it the way they are required to do it.
I followed this link because the title led me to believe I would find resource for a static array of dynamic arrays. So I will post that application incase anyone else is looking for that reference.
int main()
{
int* time[2];
int userInp;
userInp = 5;
time[0] = new int[userInp];
time[0][1] = 6;
cout << time[0][1];
delete time[0];
return 0;
}

Trouble placing int matrix array in a C++ Object

I need a variable which will hold 22 pairs of ints (positions in a grid) so I was thinking of having a matrix array. So in my header file is:
int points[22][2];
but when I put the following in the constructor of the object:
this->points = {{1,2},{2,3},...};
It says "must be a expression must be a modifiable lvalue" I've tried using the const keyword and making it a pointer in the header file as described here Expression must be a modifiable L-value
I've also tried creating a separate 2d array and then assigning it but this doesn't work either.
int points2 = {{1,2},{2,3},...};
this->points = points2;
I'm used to Java and I'm not too experienced with C++. There is a default constructor that will assign the values as above and a constructor which will have the matrix as parameter.
The following does work:
this->point[1][1] = 4;
But this means I can't pass another value as a parameter and I end up with 44 lines of messy code in the default constructor! And I was going to use a struct with 2 ints and put them in a vector put that seems like a bit of an overkill and would mean I need 22 vector inserts before I even called the constructor with the manual values and I just thought there must be a better way :)
Thanks
Since you're using C++, a much better choice would be to use a vector of pairs of ints.
Declare it like this:
std::vector<std::pair<int, int> > points;
In your constructor you can specify size at initialization
: points(22),
or set it at any point like this:
points.resize(22);
You can access individual coordinates with
points[1].first = 1;
points[1].second = 44;
or with
points[1] = make_pair(1, 44);
or you can build it up without having to worry about exceeding its allocated size with
points.push_back(make_pair(1, 44));
etc
The fundamental cause of your problem is that arrays do not count as real values in C++. They are substandard in many ways- one of which you have just encountered. Any normal type would work as you expect. Unfortunately, to those of us who are not language experts, the error Visual Studio throws is incredibly unhelpful.
You must create an array on the stack and then manually loop through and assign all the values.