vectoris easy to obtain int* through vector::data(), so how to convert vector<vector>to int**?
int main(int argc, char *argv[])
{
std::vector<std::vector<int>> temp {{1,2,3},{4,5,6}};
int **t;
t = reinterpret_cast<int **>(std::data(temp));
for (int i = 0; i < 2; ++i)
{
for (int j = 0; j < 3; ++j)
{
std::cout << t[i][j] << " ";
}
}
}
// out : 1 2 3 0 0 0
It's obviously wrong.
There is a simple "trick" to create the pointer that you need, as a temporary workaround while the code is being refactored to handle standard containers (which is what I really recommend that you should do).
The vectors data function returns a pointer to its first element. So if we have a std::vector<int> object, then its data function will return an int*. That puts us about halfway to the final solution.
The second half comes by having a std::vector<int*>, and using its data function to return an int**.
Putting this together, we create a std::vector<int*> with the same size as the original std::vector<...> object, and then initialize all elements to point to the sub-vectors:
std::vector<std::vector<int>> temp;
// ...
// Create the vector of pointers
std::vector<int*> pointer_vector(temp.size());
// Copy the pointers from the sub-vectors
for (size_t i = 0; i < temp.size(); ++i)
{
pointer_vector[i] = temp[i].data();
}
After the above loop, then you can use pointer_vector.data() to get the int** pointer you need.
Until you have refactored the code, you could put this in an overloaded function that does the conversion and calls the actual function:
// The original function
void some_function(int**);
// Creates a vector of pointers, and use it for the
// call of `some_function(int**)`
void some_function(std::vector<std::vector<int>> const& actual_vector);
Related
In this code, an array of pointers newData is created in a for loop then it is pushed into a vector testData. The pointers are stored in the vector std::vector<testData*>.
My concern is that I need to make sure that the objects referenced by the pointers remain valid while the vector holds a reference to them. Do I lose this reference by calling the line newData = new unsigned char[frameSize]; in a for loop?
I mainly want to avoid copying the objects with a push_back.
How can I create an array of unsigned char* of random char (here I just use 'a') and then push these arrays to the vector?
int numFrames = 25;
int frameSize = 100;
std::vector<unsigned char*> testData;
unsigned char *newData;
for (int i = 0; i < numFrames; i++) {
newData = new unsigned char[frameSize];
for (int j = 0; j < frameSize; j++) {
newData[j] = 'a'; // fill the frame with random data, 'a' here
}
testData.push_back(newData);
newData = 0; // ??
memset(&newData, 0, frameSize); // ??
}
std::cout << " testData " << testData.size() << "\n";
Do I lose this reference by calling the line newData = new unsigned char[frameSize]; in a for loop?
No, if done correctly it's perfectly feasible.
The are some problems in your code though, in the line memset(&newData, 0, frameSize); // ?? you're setting the memory occupied by a pointer, which is usually no more than 8 bytes (depending on the architecture) with a size of 100 bytes, this invokes undefined behavior. You may wanted:
memset(&newData, 0, sizeof newData); // ??
But this wouldn't do what you need, nullifying the pointer would make you lose access to the data, you don't want that, and you are pushing the same pointer to the vector in each iteration, you'll end up with a vector filled with the same pointer pointing to the same data.
Moving its declaration inside the for loop would solve this. You're not copying any data, instead pushing a new pointer, pointing to a new memory location, into the vector, at each new iteration.
How can I create an array of unsigned char* of random char (here I just use 'a') and then push these arrays to the vector?`
Your code should look something like this:
Live demo
#include <iostream>
#include <vector>
#include <ctime>
int main()
{
srand(time(0)); //seed, not the best randomizer but does the job here
const size_t numFrames = 25; //sizes can/should be constant and unsigned
const size_t frameSize = 100;
std::vector<unsigned char *> testData;
for (size_t i = 0; i < numFrames; i++)
{
//in each iteration a new pointer
unsigned char *newData = new unsigned char[frameSize];
for (size_t j = 0; j < frameSize; j++)
{
newData[j] = 'a' + rand() % 26; //random alphabetic char
}
testData.push_back(newData);
}
std::cout << "testData " << testData.size() << "\n";
for (size_t i = 0; i < numFrames; i++) //test print
{
for (size_t j = 0; j < frameSize; j++)
{
std::cout << testData[i][j];
}
std::cout << "\n";
}
}
Needless to say you should delete the memory you previously allocated when you no longer need it.
If you want a better random engine you can check this post Generate random numbers using C++11 random library.
Some notes:
As you're probably aware the data pointed by newData pointers can't be treated as a string, aka, a null terminated char array because, of course, they're not null terminated.
You'll need to manually manage the memory you allocated, that is to say that the memory reserved manually will also have to be deleted manually, when you're done with it.
The code corrections are for your code as it is, but as WhozCraig correctly points out, you would probably be better off using STL containers all around instead of pointers.
I am new to C++ and programming in general so i apologize if this is a trivial question.I am trying to initialize 2 arrays of size [600][600] and type str but my program keeps crashing.I think this is because these 2 arrays exceed the memory limits of the stack.Also,N is given by user so i am not quite sure if i can use new here because it is not a constant expression.
My code:
#include<iostream>
using namespace std;
struct str {
int x;
int y;
int z;
};
int main(){
cin>>N;
str Array1[N][N]; //N can be up to 200
str Array2[N][N];
};
How could i initialize them in heap?I know that for a 1-D array i can use a vector but i don't know if this can somehow be applied to a 2-D array.
How 2-or-more-dimensional arrays work in C++
A 1D array is simple to implement and dereference. Assuming the array name is arr, it only requires one dereference to get access to an element.
Arrays with 2 or more dimensions, whether dynamic or stack-based, require more steps to create and access. To draw an analogy between a matrix and this, if arr is a 2D array and you want access to a specific element, let's say arr[row][col], there are actually 2 dereferences in this step. The first one, arr[row], gives you access to the row-th row of col elements. The second and final one, arr[row][col] reaches the exact element that you need.
Because arr[row][col] requires 2 dereferences for one to gain access, arr is no longer a pointer, but a pointer to pointer. With regards to the above, the first dereference gives you a pointer to a specific row (a 1D array), while the second dereference gives the actual element.
Thus, dynamic 2D arrays require you to have a pointer to pointer.
To allocate a dynamic 2D array with size given at runtime
First, you need to create an array of pointers to pointers to your data type of choice. Since yours is string, one way of doing it is:
std::cin >> N;
std::string **matrix = new string*[N];
You have allocated an array of row pointers. The final step is to loop through all the elements and allocate the columns themselves:
for (int index = 0; index < N; ++index) {
matrix[index] = new string[N];
}
Now you can dereference it just like you would a normal 2D grid:
// assuming you have stored data in the grid
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
std::cout << matrix[row][col] << std::endl;
}
}
One thing to note: dynamic arrays are more computationally-expensive than their regular, stack-based counterparts. If possible, opt to use STL containers instead, like std::vector.
Edit: To free the matrix, you go "backwards":
// free all the columns
for (int col = 0; col < N; ++col) {
delete [] matrix[col];
}
// free the list of rows
delete [] matrix;
When wanting to allocate a 2D array in C++ using the new operator, you must declare a (*pointer-to-array)[N] and then allocate with new type [N][N];
For example, you can declare and allocate for your Array1 as follows:
#define N 200
struct str {
int x, y, z;
};
int main (void) {
str (*Array1)[N] = new str[N][N]; /* allocate */
/* use Array1 as 2D array */
delete [] Array1; /* free memory */
}
However, ideally, you would want to let the C++ containers library type vector handle the memory management for your. For instance you can:
#include<vector>
..
std::vector <std::vector <str>> Array1;
Then to fill Array1, fill a temporary std::vector<str> tmp; for each row (1D array) of str and then Array1.push_back(tmp); to add the filled tmp vector to your Array1. Your access can still be 2D indexing (e.g. Array1[a][b].x, Array1[a][b].y, ..., but you benefit from auto-memory management provided by the container. Much more robust and less error prone than handling the memory yourself.
Normally, you can initialize memory in heap by using 'new' operator.
Hope this can help you:
// Example program
#include <iostream>
struct str {
int x;
int y;
int z;
};
int main()
{
int N;
std::cin>>N;
str **Array1 = new str*[N]; //N can be up to 200
for (int i = 0; i < N; ++i) {
Array1[i] = new str[N];
}
// set value
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
Array1[row][col].x=10;
Array1[row][col].y=10;
Array1[row][col].z=10;
}
}
// get value
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
std::cout << Array1[row][col].x << std::endl;
std::cout << Array1[row][col].y << std::endl;
std::cout << Array1[row][col].z << std::endl;
}
}
}
I'm eradicating std::string in favor of C-strings, which I'm new to. How do I get the following to compile? g++ complains: cannot convert char(*)[16] to char**
#include <iostream>
void print(char** s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << '\n';
}
}
int main()
{
constexpr int n = 3;
char s[n][16]{ "Hello", "Bye", "Sky"};
print(s, n);
}
You created a multidimensional array, not an array of pointers. Usually an array can be said to be equivalent to a pointer, however in this case c++ needs to know the size of the second dimension of your array. The function would be as follows
void print(char s[][16], int n)`{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
Understandably you may want to pass the function using pointers as to not make an entire copy of the 2-d array. I saw you mentioned you were okay with variable length strings. That functionality is supported in the string library. You are dealing with c-strings which are not strings at all but static arrays of type character. Defining these c-strings using dynamic memory happens to give you the desired behavior as you create in the simplest terms an array of pointers.
void print(char** s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
int main()
{
int n = 3, i;
char** s = new char*[n];
for (i = 0; i < 3; i++) {
s[i] = new char[16];
}
s[0] = "Hello";
s[1] = "Bye";
s[2] = "Sky";
print(s, n);
for (i = 0; i < 3; i++) {
delete [] s[i];
}
delete [] s;
s = NULL;
return 0;
}
Since you are using dynamic memory now you need to free your memory which is what the last loop serves to do. As you can see using all this dynamic memory is quite taxing and it would be easier to use the string library that has been optimized to do a much better job then you can. If you're still not convinced you should at least make your own string class to handle the dynamic memory that contains a char * as its private member. In either case you avoid this mess and just make an array of zed class objects and not deal at all with multidimensional nonsense. No one likes seg faults and memory leaks.
Given any type T, T arr[N]; declares a variable arr of type T[N], which is an array and not a pointer. When you use arr in almost all contexts, array to pointer conversions happen, giving the incorrect illusion that arr is a pointer of type T*.
char s[n][16] = { "Hello", "Bye", "Sky" };
declares s as an array of n elements of type char[16]. Now, when array to pointer conversion happens, s decays into a pointer of type char (*)[16]. Hence, your function needs to have the signature
void print(char (*s)[16], int n);
Which is equivalent to
void print(char s[][16], int n);
the [] is interpreted as a pointer by the compiler.
To make these complex types more readable, a type alias may be used.
using T = char[16];
void print(T s[], int n);
Addressing some concerns
As pointed out in the comments, std::string should almost always be preferred over a char array. If you have performance concerns, benchmark before doing this. I really doubt much performance gains can be observed in most cases.
Declaring an array with length n which is an int is not standard C++. It is an extension provided by your compiler, it is not portable and in most cases not necessary.
int n = 3;
char vla[n]; // this is a variable length array
char arr[3]; // this is just an array
char* darr = new char[3]; // this is a pointer pointing to dynamically allocated memory
std::string str; // but instead, this is just better
The compiler cannot extract from char ** the infomation about char[16]. You need to define a type char[16] and pass the pointer to this type to your print function.
#include <iostream>
typedef char str_t[16];
void print(str_t* s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
int main()
{
int n = 3;
char s[n][16]{ "Hello", "Bye", "Sky"};
print(s, 3);
}
Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
class Array {
private:
// Private variables
unsigned int mCapacity;
unsigned int mLength;
void **mData;
public:
// Public constructor/destructor
Array(unsigned int initialCapacity = 10);
// Public methods
void addObject(void *obj);
void removeObject(void *obj);
void *objectAtIndex(unsigned int index);
void *operator[](unsigned int index);
int indexOfObject(void *obj);
unsigned int getSize();
};
}
Implementation:
GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
// Allocate a buffer that is the required size
mData = new void*[initialCapacity];
// Set the length to 0
mLength = 0;
}
void GG::Array::addObject(void *obj) {
// Check if there is space for the new object on the end of the array
if (mLength == mCapacity) {
// There is not enough space so create a large array
unsigned int newCapacity = mCapacity + 10;
void **newArray = new void*[newCapacity];
mCapacity = newCapacity;
// Copy over the data from the old array
for (unsigned int i = 0; i < mLength; i++) {
newArray[i] = mData[i];
}
// Delete the old array
delete[] mData;
// Set the new array as mData
mData = newArray;
}
// Now insert the object at the end of the array
mData[mLength] = obj;
mLength++;
}
void GG::Array::removeObject(void *obj) {
// Attempt to find the object in the array
int index = this->indexOfObject(obj);
if (index >= 0) {
// Remove the object
mData[index] = nullptr;
// Move any object after it down in the array
for (unsigned int i = index + 1; i < mLength; i++) {
mData[i - 1] = mData[i];
}
// Decrement the length of the array
mLength--;
}
}
void *GG::Array::objectAtIndex(unsigned int index) {
if (index < mLength) return mData[index];
return nullptr;
}
void *GG::Array::operator[](unsigned int index) {
return this->objectAtIndex(index);
}
int GG::Array::indexOfObject(void *obj) {
// Iterate through the array and try to find the object
for (int i = 0; i < mLength; i++) {
if (mData[i] == obj) return i;
}
return -1;
}
unsigned int GG::Array::getSize() {
return mLength;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &
could someone give me a brief explanation of what is happening differently in the functions below?
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
}
}
particularly what is happening differently in f2. but clearly different things are happening in each.
f1 and f3 do the same thing (but differently). f2 fails completely, and f4 is buggy (works in this example, but when i tried to put other values into other pointers (char *) the strings end up strange.)
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
The d seems to be a pointer to array of data_t's (or is a 1-element array of arrays of data_t). It is dereferenced to recover the array of data_t's and then i-th element of this array is modified.
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
This is a bit tricky and indeed does something different than in the first case. There was a pointer to array of data_t's. Here we have an array of pointers to data_t's. The pointer to first element is dereferenced to retrieve a pointer to data. Then -> is used to access the data and value is modified ( x->y = (*x).y ). Finally the pointer is moved to the next element of main array.
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
Here we have simpler case, the d is just an array of data_t's accessed by pointer. Inside the loop, an element is accessed by ->, and then d is incremented to point to next element of array.
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
}
}
Similarly to f3, elements are modified by the [] operator.
Note the following facts:
int[] =(def) int *
if a is of type int * and i is of any integral type, then:
*(a + i) =(def) a[i]
Also, if a points to first element of an array, then
*a =(def) a[0]
and then, after a "a++"
*a =(def) a[1]
...and so on.
Let's take these one at a time:
// f1
(*d)[i].ival = i;
First, (*d) is dereferencing d, which appears to be a pointer to an array of data_t variables. This allows access to the actual array, such that [i] is accessing the i-th element of the array and assigning i to it.
// f2
(*d)->ival = i;
(*d)++;
(*d) is dereferencing d just like in the first one. However, there is one crucial bit of information about arrays that you should understand before moving on...
int j[2] = { 42, 50 };
int j0 = *j; // j0 is now 42
j += 1;
int j1 = *j; // j1 is now 50
Arrays are implemented as individual variables sequentially oriented in "slots" in memory, and an array is really just a pointer to the first slot. As such, *j is dereferencing j, which is currently pointing to the first element, resulting in 42. Doing j += 1 advances the pointer by one "slot", such that *j will now result in 50.
Now, back to f2. (*d)->ival is exactly like doing (**d).ival. This is very much like the simple example I gave above. The next line, (*d)++, is advancing the pointer to the next "slot". Consider this simple diagram of what's "happening" in memory:
+------+------+
|*(j+0)|*(j+1)|
j --->|------|------|
| 42 | 50 |
+------+------+
with j pointing to the first "slot", the dereference shown in the first row, the value in the second.
f3 is very much like f2, except that it expects the array to be passed as an argument, instead of a pointer to it. Hence, d only needs to be dereferenced once with the -> operator (again, exactly like (*d).ival).
f4is very much like f1, except that it expects the array to be passed as an argument, instead of a pointer to it. Hence, d[i] is directly accessing the i-ith element of the array.
void f1(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)[i].ival = i;
}
}
You get a pointer to array **d of data_t ,which element is a structure,having a field ival
Access the array *d
Iterate all array elements,element by element,changing indices i.And updating ival of each array element by to be i
Note:You dont change the pointer*d`,pointing to array beginning
void f2(data_t **d)
{
for (int i=0; i<MAXSIZE; i++)
{
(*d)->ival = i;
(*d)++
}
}
You get a pointer to array **d of data_t ,which element is a structure,having a field ival
Access the array *d,which is also a pointer to the array (first element)
Updating ival of the (above) element by to be i,using pointer notation (*d)->ival = i;
Promote the pointer to the next array element (*d)++ and return to 2.From now on *d is
pointing to the "sifted"array beginning.
void f3(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d->ival = i;
d++;
}
}
1.You get an array *d of data_t ,which element is sa structure,having a field ival.
2.It also can be considered you get a pointer to the first element of array.
Access access and update ival to be i,by pointer: d->ival = i;
3.Promote the pointer to the next array element d++
void f4(data_t *d)
{
for (int i = 0; i<MAXSIZE; i++)
{
d[i].ival = i;
d++;
}
}
As in f3.But you promote indices and update ival using reference notation (by value)