I'm trying to copy the data present in an array of pointers to another one.
I have very few knowledge in C++, but some in higher level languages.
Here is a sample code of what I've achieved so far (simplified version):
#define MAX_ACTIVE_MODES 3
myStruct_t priorities1[MAX_ACTIVE_MODES];
myStruct_t *priorities2[MAX_ACTIVE_MODES];
for (unsigned short i = 0; i < MAX_ACTIVE_MODES; ++i) {
priorities2[i] = (myStruct_t*)malloc(sizeof(myStruct_t));
memcpy(priorities2[i], &priorities1[i], sizeof(myStruct_t));
}
// ...
delete[] *priorities2;
It's easier for me to have a non pointer var for priorities1 and have one for priorities2 because I'm passing it to a sort function.
When I search for solutions, there's never the case of type *var[] and I don't get why.
Even though your question is tagged c++, I assume that you are programming in C based on your use of malloc.
First you don't need to use memcpy to copy structs.
*priorities2[i] = priorities1[i];
should be equivalent to
memcpy(priorities2[i], &priorities1[i], sizeof(myStruct_t));
Second, you don't have to create copies of the elements in priorities1[]. Just have the pointers in priorities2[] point to the elements in priorities1[]:
for (size_t i = 0; i < MAX_ACTIVE_MODES; ++i)
{
priorities2[i] = &priorities1[i];
}
As long as you don't access priorities2 beyond the lifetime of priorities1, no malloc or free is needed.
Related
For an assignment, I had to separate some code for Conway's Game of Life into multiple files, but now I'm trying to get a deeper understanding of why the code was written the way it was. I have a class, World, and part of the constructor for that class looks like this:
world.h:
class World {
public:
// Constructor/destructor
World();
~World();
void updateWorld();
...
private:
char **m_grid_1;
char **m_grid_2;
...
};
world.cpp:
World::World()
{
m_toggle = true;
m_grid_1 = new char*[MAX_ROWS];
m_grid_2 = new char*[MAX_ROWS];
for (int i = 0; i < MAX_ROWS; i++) {
m_grid_1[i] = new char[MAX_COLS];
m_grid_2[i] = new char[MAX_COLS];
}
...
}
MAX_ROWS and MAX_COLS are globals that live in a header now.
Arrays have always kind of confused me, so these questions might seem kind of basic:
What does char** mean in the context of the member variable m_grid_1 or m_grid_2? Pointer to a pointer of chars? Those members are 2D arrays, so I'm not sure why pointers are used here instead.
Why is new used here in combination with that loop in the constructor? Couldn't you just say m_grid_1[MAX_ROWS][MAX_COLS];?
Also, rather than toggle between the two grids, if I wanted to make a local copy of m_grid_1 in the member function updateWorld() and use that local copy to get the next state of the game, would I need to use new? This is what I have now, and it seems to work, but I'm not sure if I'm doing something wrong by not dynamically allocating the 2D array here:
void World::updateWorld() {
char grid_copy[MAX_ROWS][MAX_COLS];
for (int i = 0; i < MAX_ROWS; i++) {
for (int j = 0; j < MAX_COLS; j++) {
grid_copy[i][j] = m_grid_1[i][j];
}
}
// loop over grid_copy to find next state of m_grid_1
}
Do all arrays in C++ classes have to be dynamically allocated?
Not in general.
or just their member variables?
Member variables don't have to be allocated dynamically either.
What does char** mean ... Pointer to a pointer of chars?
It is a pointer to pointer to char.
Those members are 2D arrays
Correction: Those members are pointers. They used pointers, therefore they are not arrays.
Why is new used here in combination with that loop in the constructor?
Because the author of the program chose to use it.
Couldn't you just say m_grid_1[MAX_ROWS][MAX_COLS];?
Maybe. If MAX_ROWS and MAX_COLS are compile time constant and if they are small, then sure.
If I wanted to make a local copy of m_grid_1 in the member function updateWorld() and use that local copy to get the next state of the game, would I need to use new?
If the question is whether you need dynamic allocation, then maybe. See the answer above.
There is hardly ever need to use new. A simpler and safer way to create a dynamic array is to use std::vector.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I am a C/C++ newbie, so sorry if my question seems straightforward.
It has always been claimed that pointers in C++ are useless. See for example the answer from Konrad Rudolph here https://softwareengineering.stackexchange.com/questions/56935/why-are-pointers-not-recommended-when-coding-with-c
Below I have an example for which I am wondering how can I replace the C code by a C++ code without using any pointers:
double *A;
double **a;
A=new(std::nothrow) double[4];
a=new(std::nothrow) double*[2];
for (unsigned int q=0, k=0; k < 2; k++)
{
a[k]=A + q;
q+=2;
}
delete[] A;
delete[] a;
The programmer codes up as above because he/she needs the pointer a to point to the pointer A so that when modifying the variable to which A points, he/she does not to modify a.
Sometimes, the programmer does a for loop with a[k] from k={0,1,2,3}, and sometimes he does a double for loop a[i][j] from i,j={0,1}.
How can I replace this by a C++ code without using pointers?
Some important clarity: what you're being advised is to not use Raw, Owning Pointers. It's perfectly fine to use Non-Owning Raw Pointers iff you know, as a fact, that you're not responsible for deleteing said memory; or Owning Smart Pointers iff you are responsible for said memory, but deleteing will be handled by the RAII principles of the smart pointer class.
So let's consider what's happening in your code:
A represents ownership over a runtime-sized array of doubles.
a represents ownership over a runtime-sized array of non-owning pointers to doubles, all of which will come from A.
Simply creating an array of objects is either best represented by std::array, for compile-time-sized arrays, or std::vector, for runtime-sized arrays. So we'll need the latter. This is easy to construct:
std::vector<double> A(4);//Array of 4 doubles.
Since a will contain non-owning pointers to A, which we know will outlive a, it's perfectly fine to use raw pointers inside this vector:
std::vector<double*> a(2);
Then, we assign into it, just like your code was already doing:
//Use size_t for sizes in C++. Always, always, always.
for (size_t q = 0, k = 0; k < 2; k++){
a[k] = A + q;//Uh oh, this doesn't compile!
q += 2;
}
Ah, hmm. A isn't a raw pointer anymore. Well, we'll need to use a member function of std::vector to get the raw pointer.
//Use size_t for sizes in C++. Always, always, always.
for (size_t q = 0, k = 0; k < 2; k++){
a[k] = A.data() + q;//There we go.
q += 2;
}
Finally, because our memory is RAII-managed, we don't need to delete this memory afterwards:
//No longer needed
//delete[] A;
//delete[] a;
So the final code will end up looking like this:
std::vector<double> A(4);
std::vector<double*> a(2);
for (size_t q = 0, k = 0; k < 2; k++){
a[k] = A.data() + q;
q += 2;
}
This code is nearly identical to the C-style code you wrote originally, and is much easier to read and maintain. The only difference is the small amount of overhead in std::vector, which the compiler can optimize away for the final program.
If you want code which literally emulates the behavior of your original code, this would be the result. I don't recommend it, because it's more complicated than you need, and limits how the code can be used, but if you just want the direct port (or just want to see how Smart Pointers fit into this kind of problem), here it is:
std::unique_ptr<double[]> A = std::make_unique<double[]>(4);
std::unique_ptr<double*[]> a = std::make_unique<double*[](2);
for (size_t q = 0, k = 0; k < 2; k++){
a[k] = A.get() + q;
q += 2;
}
One of the primary uses of pointer-to-pointer in C is to return a pointer value:
error_t Allocate Object(Object ** ptr);
While the same will work in C++ it can be made somewhat more intuitive by making the function take a reference-to-pointer instead of pointer-to-pointer:
error_t AllocateObject(Object *& ref);
This way the calling code can simply pass the pointer variable (instead of needing to use & to take its address) and the function definition can simply assign to the parameter (rather than needing to dereference it with *).
The modern C++ equivalent of your example code would use smart pointers for ownership, and iterators to access array elements:
#include <array>
#include <memory>
int main()
{
// Define our types:
using A_array = std::array<double, 4>;
using A_iterator = A_array::iterator;
// Make smart pointers to manage ownership for us:
auto const A = std::make_unique<A_array>();
auto const a = std::make_unique<std::array<A_iterator, 2>>();
// Normally, we'd just put these in automatic storage, as
// they are small, and don't outlive the function scope:
// A_array A;
// std::array<A_iterator, 2> a;)
{
// Populate a with iterators to A's elements
auto target = A->begin();
for (auto& element: *a) {
element = target;
target += 2;
}
}
// No need for delete[] at end of function or at any other
// return statement.
}
I work with CPLEX and C++ via Concert Technology and a recurrent issue I am encountering is that internally the IloArray structures seem to be overloaded vector structures with copy-by-reference operators. Which I must acknowledge is a quite neat and memory efficient way of handling the array structures.
Yet... This implies that making IloIntArray Array_copy = Array, for a previously declared and initialized IloIntArray Array, will make a reference copy of Array into Array_copy. Hence, any change in Array is automatically transferred to Array_copy. The same applies to multi-dimensional IloArray structures via the add() routine.
Let us say, for instance, that I need to populate a 2D IloArray<IloIntArray> Array2D(env), inside a for-loop indexed in i = 1 to iSize, storing in each position of Array2D[i], from i = 1 to iSize, the values of Array which will be different at each iteration of the loop. Making either:
Array2D[i].add(Array) or,
Array2D[i] = Array, assuming Array2D i-dimension was initially set to be of size iSize.
Fails to make the intended copy-by-value, since each time, a copy-by-reference is made to the elements of the i-dimension and you end up with all identical elements, equal to the last value of Array.
Now, besides, making my own copy-by-value operator constructor (Option I) or a copy routine (Option II) receiving, both, the origin and destination arrays as well as the position of the destination array (e.g. multi-dimensional array) where the origin array is to be copied.
Is there another way to make the copy-by-value? In any case, can you help me decide which one of these options is more neat and/or memory efficient? Intuitively I deem Option I to be the more efficient, but I don't know how to do it...
Thanks in advance for your help
Y
So far, I am solving my own issue by implementing a copy() function.
I have typedefed my multi-dimensional arrays as follows:
typedef IloArray<IloIntArray> Ilo2IntArray; and typedef IloArray<IloNumArray> Ilo2NumArray and so on for three or four dimensional integer or numeric arrays.
An example of my Ilo3IntArray copy(Ilo3IntArray origin) overload of the copy function I am using as a patch to make copy-by-value copies, is as follows:
Ilo3IntArray copy(Ilo3IntArray origin) {
IloInt iSize = origin.getSize();
Ilo3IntArray destination(env, iSize);
IloInt jSize = origin[0].getSize();
IloInt zSize = origin[0][0].getSize();
for (IloInt i = 0; i < iSize; i++) {
destination[i] = Ilo2IntArray(env, jSize);
for (IloInt j = 0; j < jSize; j++) {
destination[i][j] = IloIntArray(env, zSize);
for (IloInt z = 0; z < zSize; z++) {
destination[i][j][z] = origin[i][j][z];
}
}
}
return destination;
// Freeing Local Memory
destination.end();
}
Your comments and/or better answers are welcome!!!
Inside a function, I make a 2d array that fills itself from a text file and needs to get returned to main. The array stays a constant size through the whole program.
I know this is something that gets asked a lot, but I always seem to get one of two answers:
Use std::vector or std::array or some other STD function. I don't really understand how these work, is there any site actually explaining them and how they act compared to normal arrays? Are there any special #includes that I need?
Or
Use a pointer to the array, and return the pointer. First, on some of the answers to this it apparently doesn't work because of local arrays. How do I tell when it does and doesn't work? How do I use this array back in the main function?
I'm having more trouble with the concept of pointers and std::things than with the actual code, so if there's a website you know explains it particularly well, feel free to just put that.
Not necessarily the best solution, but the easiest way to get it working with vectors. The advantages are that you don't need to delete memory (happens automatically) and the array is bounds-checked in debug mode on most compilers.
#include <vector>
#include <iostream>
using array2D = std::vector< std::vector< int > >;
array2D MyFunc(int x_size, int y_size)
{
array2D array(y_size, vector< int >(x_size));
int i = 0;
for (int y = 0; y < array.size(); y++)
{
for (int x = 0; x < array[y].size(); x++)
{
// note the order of the index
array[y][x] = i++;
}
}
return array;
}
int main()
{
array2D bob = MyFunc(10, 5);
for (int y = 0; y < bob.size(); y++)
{
for (int x = 0; x < bob[y].size(); x++)
{
cout << bob[y][x] << "\n";
}
}
}
Live example:
http://ideone.com/K4ilfX
Sounds like you are new to C++. If this is indeed the case, I would suggest using arrays for now because you probably won't be using any of the stuff that STL containers give you. Now, let's talk about pointers.
You are correct that if you declare a local array in your function, the main function won't have access to it. However, this is not the case if you dynamically allocate the array using the new keyword. When you use new to allocate your array, you essentially tell the compiler to reserve a chunk of memory for your program. You can then access it using a pointer, which is really just the address of that chunk of memory you reserved. Therefore, instead of passing the entire array to the main function, all you need to do is pass a pointer (address) to that array.
Here are some relevant explanations. I will add to them as I find more:
Dynamic Memory
The easiest way to create a 2d array is as follows:
char (*array)[10];
array = new array[5][10];
Two dimensional arrays can be tricky to declare. The parenthesis above in the variable declaration are important to tell the compiler array is a pointer to an array of 10 characters.
It is really essential to understand pointers with C and C++ unless using the std:: collections. Even then, pointers are widely prevalent, and incorrect use can be devastating to a program.
I'm moving from Objective-C to C++ and am not sure what vectors are. I've read documentation about them, I'm not quite clear though. How would you explain C++ vectors using Objective-C analogies?
They're pretty similar to NSMutableArrays but vector is a template class and so can be instanciated for any (standard-template-library compatible) type. NSArrays always hold NSObjects.
That is, assuming you mean std::vector.
They're like NSMutableArrays but can hold any data type - pointer or not. However, each vector can only ever hold one type at a time. Also as it's C++ there are fewer functions e.g. no plist loading/saving.
A C++ vector (presumably you mean something like std::vector) is basically an NSArray, except it holds any type you want (which is the template parameter, e.g. a std::vector<int> holds ints). Of course, it doesn't do memory management (which NSArray does), because arbitrary types aren't retain-counted. So for example a std::vector<id> would be rather inappropriate (assuming Obj-C++).
NSArray is a wrapper around CFArray. CFArray can store any data type.
I don't know much about C++, but it sounds like CFArray can do everything you'd use a vector for? When creating a CFArray you give it a CFArrayCallBacks pointer, which contains any logic that is specific to the data type being stored.
Of course, you could always just rename your Obj-C file to *.mm, and mix C++ into your objective-c.
http://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFArrayRef/Reference/reference.html
In C++ an Array is basically just a pointer to a contiguous block of data---a series of elements. It offers no built-in methods, or higher functionality.
int intArr[] = {0,1,2,3};
is the same as
int *intArr = (int *)malloc(4*sizeof(int));
for(int i = 0; i < 4; i++) { intArr[i] = i; }
A vector (std::vector), on the other hand, is a container for elements (basically like an array) which also offers additional built in methods (see: http://www.cplusplus.com/reference/stl/vector/) such as
vector<int> intArr;
for(int i = 0; i < 4; i++) { intArr.push_back(i); }
// this yields the same content; i.e. intArr = {0,1,2,3}
Both arrays and vectors can be used on any type of objects, int, double, 'MySpacePirateWizardClass' etc. The big bonus of vectors is the additional functionality from built-in functions like:
int arrSize = intArr.size(); // vector also includes useful information
int *firstElement = intArr.begin(); // methods for creating pointers to elements
intArr.delete(0); // modify elements
intArr.insert(0, 2); // modify vector
// now: intArr = {2,1,2,3}
etc etc.
When I know I'm not going to be short on space (or looking at massive amounts of data), I always use vectors because they're so more convenient (even just the size() method alone is reason enough).
Think about vectors as advanced arrays.
If you are new to C++, this page will be your best friend:
http://www.cplusplus.com/reference/stl/vector/