I am new to C++ arrays and pointer and came across a few problems. I have some inquiries for the following code I wrote.
Version 1:
int main()
{
string a, b;
int age;
Dog d[5];
Dog *p = new Dog[5];
for (int i = 0; i < 5; i++)
{
d[i].setwe(3 * i);
d[i].setag(i);
p[i] = Dog(d[i]);
}
p[5]->showCnt();
//^^^^^^^^^^^^^^ Error above
for (int j = 0; j < 5; j++)
{
delete [] p;
}
return 0;
}
Version 2:
int main()
{
string a, b;
int age;
Dog d[5];
Dog *p[5];
for (int i = 0; i < 5; i++)
{
d[i].setwe(3 * i);
d[i].setag(i);
//p[i] = Dog(d[i]);
p[i] = &d[i];
}
p[5]->showCnt();
return 0;
}
From what I understand I might have written wrongly in version 1 but I want to understand why p is not seen as a pointer in version 1?
This is the hint I got from error: base operand of '->' has non pointer-type 'Dog'.
I am also unsure which is a better way(version 1 or version 2) to copy an object array to a pointer object array.
I would like to apologise in advanced if I have understood it wrongly. Thank you.
p[5]->showCnt() is ilegal because your array of objects has only 5 positions, starting by 0 and ending on 4. So, you just have to replace p[5]->showCnt() by p[4]->showCnt().
About the better version to use, use version 2 if you want to work with static sizes and use version 1 if you want to manage p dynamically to work with more than 5 objects at some moment of your program runtime. Short answer: version 1 is better!
Related
#include <iostream>
using namespace std;
int* computeSquares(int& n)
{
int arr[10];
n = 10;
for (int k = 0; k < n; k++)
arr[k] = (k + 1) * (k + 1);
return arr;
}
void f()
{
int junk[100];
for (int k = 0; k < 100; k++)'
junk[k] = 123400000 + k;
}
int main()
{
int m;
int* ptr = computeSquares(m);
f();
for (int i = 0; i < m; i++) {
cout << ptr[i] << ' ';
}
}
The above code should print:
1 4 9 16 25 36 49 64 81 100
However, it instead prints random integer values that don't make any sense, at least after the first one. After running the code through the debugger, the ptr address is deleted right after the first run of the for loop in the main method and I cannot fathom why. Additionally, I have no idea what the purpose of the f() method is, I don't think it should change anything but when I remove it from the main the first value returns accurately (everything after is still wrong.) What is going on?
Try this:
int *computeSquares(int &n) {
int *arr = new int[10];
n = 10;
for (int k = 0; k < n; k++)
arr[k] = (k + 1) * (k + 1);
return arr;
}
The memory of "int arr[10]" is released after computeSquares finished running.
You are getting this result because you are misunderstanding basic language features. In addition to MsrButterfly's answer, who pointed out the most important problem already, let me please give you the following advices:
forget about using raw pointers; it is dangerous practice, very hard to maintain and extend, and will for sure lead you to write code with memory leaks. You will be better off having a look at some STL documentation which possesses e.g. the std::vector container that you could use instead of your array arr
your computeSquares method is dangerous in the sense that you take a variable n a argument which should be your array's size. In your method, you first define arr with a hard-coded size of 10 and then you set n = 10; I'd suggest you avoid that kind of constructs as you have in this case to maintain two variables that depend on that number 10.
I'm having problems declaring a multidimensional dynamical array in c style. I want to declare dynamically an array like permutazioni[variable][2][10], the code i'm using is as following (carte is a class i defined):
#include "carte.h"
//other code that works
int valide;
carte *** permutazioni=new carte**[valide];
for (int i=0; i<valide; i++){
permutazioni[i]=new carte*[2];
for (int j=0; j<2; j++) permutazioni[i][j]=new carte[10];
}
the problem is, whenever i take valide=2 or less than 2, the code just stops inside the last for (int i=0; i<valide; i++) iteration, but if i take valide=3 it runs clear without any problem. There's no problem as well if i declare the array permutazioni[variable][10][2] with the same code and any value of valide. I really have no clue on what the problem could be and why it works differently when using the two different 3d array i mentioned before
You show a 3D array declared as permutazioni[variable][10][2] but when you tried to dynamical allocate that you switched the last two dimensions.
You can do something like this:
#include <iostream>
#define NVAL 3
#define DIM_2 10 // use some more meaningfull name
#define DIM_3 2
// assuming something like
struct Card {
int suit;
int val;
};
int main() {
// You are comparing a 3D array declared like this:
Card permutations[NVAL][DIM_2][DIM_3];
// with a dynamical allocated one
int valid = NVAL;
Card ***perm = new Card**[valid];
// congrats, you are a 3 star programmer and you are about to become a 4...
for ( int i = 0; i < valid; i++ ){
perm[i] = new Card*[DIM_2];
// you inverted this ^^^ dimension with the inner one
for (int j = 0; j < DIM_2; j++)
// same value ^^^^^
perm[i][j] = new Card[DIM_3];
// inner dimension ^^^^^
}
// don't forget to initialize the data and to delete them
return 0;
}
A live example here.
Apart from that it is always a good idea to check the boundaries of the inddecs used to access to the elements of the array.
How about using this syntax? Haven't tested fully with 3 dimensional arrays, but I usually use this style for 2 dimensional arrays.
int variable = 30;
int (*three_dimension_array)[2][10] = new int[variable][2][10];
for(int c = 0; c < variable; c++) {
for(int x = 0; x < 2; x++) {
for(int i = 0; i < 10; i++) {
three_dimension_array[c][x][i] = i * x * c;
}
}
}
delete [] three_dimension_array;
Obviously this could be c++ 11/14 improved. Could be worth a shot.
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 &
I have been working on this program for quite some time. This is just two of the functions extracted that are causing a memory leak that I cant seem to debug. Any help would be fantastic!
vector<int**> garbage;
CODE for deleting the used memory
void clearMemory()
{
for(int i = 0; i < garbage.size(); i++)
{
int ** dynamicArray = garbage[i];
for( int j = 0 ; j < 100 ; j++ )
{
delete [] dynamicArray[j];
}
delete [] dynamicArray;
}
garbage.clear();
}
CODE for declaring dynamic array
void main()
{
int ** dynamicArray1 = 0;
int ** dynamicArray2 = 0;
dynamicArray1 = new int *[100] ;
dynamicArray2 = new int *[100] ;
for( int i = 0 ; i < 100 ; i++ )
{
dynamicArray1[i] = new int[100];
dynamicArray2[i] = new int[100];
}
for( int i = 0; i < 100; i++)
{
for(int j = 0; j < 100; j++)
{
dynamicArray1[i][j] = random();
}
}
//BEGIN MULTIPLICATION WITH SELF AND ASSIGN TO SECOND ARRAY
dynamicArray2 = multi(dynamicArray1); //matrix multiplication
//END MULTIPLICATION AND ASSIGNMENT
garbage.push_back(dynamicArray1);
garbage.push_back(dynamicArray2);
clearMemory();
}
I stared at the code for some time and I can't seem to find any leak. It looks to me there's exactly one delete for every new, as it should be.
Nonetheless, I really wanted to say that declaring an std::vector<int**> pretty much defies the point of using std::vector itself.
In C++, there are very few cases when you HAVE to use pointers, and this is not one of them.
I admit it would be a pain to declare and use an std::vector<std::vector<std::vector<int>>> but that would make sure there are no leaks in your code.
So I'd suggest you rethink your implementations in term of objects that automatically manage memory allocation.
Point 1: If you have a memory leak, use valgrind to locate it. Just like blue, I can't seem to find a memory leak in your code, but valgrind will tell you for sure what's up with your memory.
Point 2: You are effectively creating a 2x100x100 3D array. C++ is not the right language for this kind of thing. Of course, you could use an std::vector<std::vector<std::vector<int>>> with the obvious drawbacks. Or you can drop back to C:
int depth = 2, width = 100, height = 100;
//Allocation:
int (*threeDArray)[height][width] = malloc(depth*sizeof(*threeDArray));
//Use of the last element in the 3D array:
threeDArray[depth-1][height-1][width-1] = 42;
//Deallocation:
free(threeDArray);
Note that this is valid C, but not valid C++: The later language does not allow runtime sizes to array types, while the former supports that since C99. In this regard, C is more powerful than C++.
I have a struct named person as follows:
struct person {
int height, weight;
};
I also created an array of person as follows:
struct Arrayofperson {
int len; //indicates the length of this array(its supposed to be dynamic)
person *p; //this is supposed to be the dynamic array of person.
};
And I do this for an array of array of person as follows:
struct Array_2d_ofperson{
int len; //indicates the length of this array(its supposed to be dynamic)
Arrayofperson *subarray; //this is supposed to be the dynamic 2d array of person.
};
This is my code:
#include <iostream>
#include "test.h"
using namespace std;
#define DLLEXPORT extern "C" __declspec(dllexport)
DLLEXPORT Arrayofperson create_arr_person(int len) {
Arrayofperson arr_p;
arr_p.len = len;
arr_p.p = new person[len];
//populate the array here:
for (int a = 0; a < len; a++) {
arr_p.p[a].height = a; //yes they're the same, but it doesn't matter for now.
arr_p.p[a].weight = a;
};
return arr_p;
}
DLLEXPORT void print_arr_person(Arrayofperson pp) {
printf("length: %d\n", pp.len);
for (int b = 0; b < pp.len; b++) {
printf("height, weight %d, %d\n", pp.p[b].height, pp.p[b].weight);
};
}
DLLEXPORT Array_2d_ofperson create_2darr_person(int len, int sublen) {
Array_2d_ofperson arr_2d_person;
arr_2d_person.len = len;
arr_2d_person.subarray = new Arrayofperson[len];
for (int a = 0; a < len; a++) {
arr_2d_person.subarray[a].len = sublen;
arr_2d_person.subarray[a].p = new person[sublen];
for (int b = 0; b < sublen; b++) {
arr_2d_person.subarray[a].p[b].height = b;
arr_2d_person.subarray[a].p[b].weight = b;
}
};
for (int a = 0; a < len; a++) {
for (int b = 0; b < sublen; b++) {
printf("(a, b): %d, %d", arr_2d_person.subarray[a].p[b].height, arr_2d_person.subarray[a].p[b].weight);
printf("\n");
}
};
return arr_2d_person;
cin.get();
}
DLLEXPORT void print_2darr_person(Array_2d_ofperson pp) {
int len = pp.len;
int sublen = pp.subarray[0].len; //yes I haven't forgotten that it can change between different subarrays.
for (int a = 0; a < len; a++) {
for (int b = 0; b < sublen; b++) {
printf("(a, b): %d, %d", pp.subarray[a].p[b].height, pp.subarray[a].p[b].weight);
printf("\n");
}
};
}
I intend to make a dll(the why is not important here) from the above code(it will have more code later on) and use it in python. So here are my questions:
1) It seems that when I do this on the python side:
from ctypes import *
test = CDLL('test.dll') //the dll from the code above, yes it works.
arr = test.create_arr_person(6)
test.print_arr_person(arr)
arr2 = test.create_2darr_person(2, 3)
#test.print_2darr_person(arr2)
raw_input('h')
I get garbage for printing the array of person and get an access violation error from windows when I try to print the 2d array.
So here are my questions, in order of importance(I don't want to use python api within the dll, because the dll could also be used by other languages)
1) How do I make it so that the memory dedicated to the array/ 2darray stays in memory so that I don't get access violation errors. I've tried doing static Arrayofperson, but it didn't work.
2) How is possible to make it easy to access person in the subarray of the 2d array instead of doing.
pp.subarray[a].p[b]. (I want to do this: pp[a][b], where pp is 2darray of person). I believe it has something to do with overloading the [ ] operator, but I'm not familiar with making classes(thats why i made a struct now).
3) How do I access the array/2darray in python using the same way (I want to do this in python:
test = CDLL('test.dll')
array_of_person = test.create_arr_person(5)
print (array_of_person[0]) #something like this
The problem here is that python does not know how to handle your struct. Check the documentation for ctypes, it has a list of supported python types that you can pass to C functions, and documentation on how to make it handle some more types.
The way you've written it, python thinks that all your functions return an int.
You need to read http://docs.python.org/library/ctypes.html
EDIT:
If you do things right, you will probably end up returning an opaque pointer to your struct from your C function to python. Inside your struct, you can use all C++ features then, including the good stuff, like std::vector.
I tried to compile your code on a Linux machine (gcc 4.4.3) and it works.
Have you considered using STL containers (vector) instead? You can use vectors of vectors to generate multidimensional arrays without having to worry about memory leaks.
You can use the fact that the vector is guaranteed to be a continuous chunk of memory and return a pointer to the first element.
T * p = &v[0]
This pointer can be then accessed as an ordinary array and is safe across module boundaries.
The same technique also works for std::strings that can be accessed via a raw pointer to the storage.
const char * p = s.c_str();
You just have to ensure the object that holds the storage does not accidentally go out of scope before you are done.
Multidimensional arrays can be always projected onto one dimension.
1 1 1
2 2 2
3 3 3
can be stored as:
1 1 1 2 2 2 3 3 3