How to access dynamic array inside a class constructor? - c++

How do I access the dynamic array and set values to it? For example array[size] = {8, 4, 3, 2, ...}
class Array
{
public:
Array(int sze)// default constructor
{
size = sze;
ptr = new int [size];
}
private:
int size; // number of elements in the Array
int *ptr = 0; // address of dynamically allocated memory
};
int main()
{
Array arry(10);
cout << arry.getSize();
//.....;
}

Your array that you have created is private, and to access it you must provide an accessor method:
public:
...
int* getPtr() { return ptr; }
...
int *ptr = arry.getPtr();
ptr[0] = 1;
cout << ptr[0];
Alternatively you can hide the pointer itself and provide get(position) and set(position) methods to ensure that other code doesn't mess with your pointer.

Related

How can I initialize an array in C++ with a size that is given to the constructor?

I have a C++ class with a member that is supposed to be a two dimensional array. I want to declare my array as a member in the header file of the class. Then in the constructor of my class I want to initialize my array with a size (given to the constructor) and fill it with zeros.
I have a working example of what I want in java:
class Obj {
int[][] array;
public Obj(int sizex, int sizey) {
array = new int[sizex][sizey];
}
}
public class Main
{
public static void main(String[] args) {
Obj o = new Obj(12,20);
}
}
I do not want to mess with pointers or alloc() and free(). As my class is supposed to be basically a wrapper for this array, I want to keep it simple.
I have thought about using std::vector, but as the array is never being resized after its initialization, I feel like vector is a little overpowered... Is there a better way than this: ?
#include<vector>
class Obj {
std::vector<std::vector<int>> array;
public:
Obj(int xsize, int ysize) {
std::vector<std::vector<int>> newArray(xsize, std::vector<int>(ysize, 0));
array = newArray;
}
};
int main()
{
Obj o(12,20);
}
std::vector is the best match here. (As you said, in most cases raw arrays and pointers could be avoided. Also see How can I efficiently select a Standard Library container in C++11?)
And you can initialize the data member directly in member initializer list instead of assigning in the constructor body after default-initialization, e.g.
Obj(int xsize, int ysize) : array(xsize, std::vector<int>(ysize, 0)) {
}
Other than using std::vector you can just allocate memory of the required size from the heap.
class Obj {
int** arr;
int x, y;
public:
Obj(int sizex, int sizey) : x(sizex), y(sizey) {
arr = new int*[sizex];
for (unsigned i = 0; i < sizex; i++) {
arr[i] = new int[sizey];
}
}
//IMPORTANT TO DELETE, OTHERWISE YOU'LL GET A MEMORY LEAK
~Obj() {
for (unsigned i = 0; i < x; i++) {
delete[] arr[i];
}
delete[] arr;
}
}

freeing the same memory with distructors

I try to free the memory correctly after the program ends, but I always encounter a problem.
In my code I want to have an array of all the numbers that I allow in my program, and have objects A and B (or more) that each one have some of the numbers that I allowed.
In the end I want to delete 'a' and 'b' only after "ints" getting out of the scope. But A and B calls their distructors to delete some of ints variables.
#define MAX_LEN 255
class IntArray
{
public:
int len;
void add(int* n) {
arr[len] = n; len++;
}
IntArray() : arr(new int* [MAX_LEN]), len(0) {}
~IntArray() {
for (int i = 0; i < len; i++)
delete arr[i];
delete[] arr;
}
private:
int** arr;
};
class Object
{
public:
void add(int* n) {
myIntArr.add(n);
}
private:
IntArray myIntArr;
};
int main(void)
{
int* a = new int(5);
int* b = new int(6);
IntArray ints;
ints.add(a);
ints.add(b);
Object A;
A.add(a);
Object B;
B.add(b);
return 0;
}
If you want to share dynamically allocated ints between multiple objects, use std::shared_ptr<int>.
Also, rather than writing a dynamic array type yourself, use std::vector to do it (correctly) for you.
using int_ptr = std::shared_ptr<int>;
class IntArray
{
public:
void add(int_ptr n) {
arr.push_back(n);
}
private:
std::vector<int_ptr> arr
};
class Object
{
public:
void add(int_ptr n) {
myIntArr.add(n);
}
private:
IntArray myIntArr;
};
int main(void)
{
int_ptr a = std::make_shared<int>(5);
int_ptr b = std::make_shared<int>(6);
IntArray ints;
ints.add(a);
ints.add(b);
Object A;
A.add(a);
Object B;
B.add(b);
return 0;
}
If you just want to have a copyable array of int, use std::vector<int>.
You're deleting a and b twice.
You should only delete something returned by new and exactly once.
But you add them both to IntArray ints; and then one each to Objects A and B and their destructors delete them also. Destructors are called in reverse order to it's when ints is destructed you'll be deleting them again - that's "Undefined Behaviour" but normally a catastrophic failure (crash) either immediately or later during executon.
The shortest fix is:
int* a = new int(5);
int* b = new int(6);
int *ac = new int(*a);//copy of *a
int *ab = new int(*b);//copy of *b
IntArray ints;
ints.add(a);
ints.add(b);
Object A;
A.add(ac);
Object B;
B.add(bc);
But it's not clear what our intention is. IntArray isn't an array of int as it stands, it's an array of pointers to int (which have been allocated by new).
My 'fix' will mean if you modify a (e.g. *a=20) you won't modify the copy (ac) added to the Object A.

How to add data to an array of pointers?

I created an array of pointers.
I want to know how to prp=operly add data to my array of pointers.
I have attempted the code below, unfortunately it is giving me a memory error and I do not know why.
class dataClass {
int data;
public:
void setdata(int d) {data = d;}
int getdata() const {return data;}
};
int main() {
dataClass** ptr = new dataClass*s[5];
int num = 9;
ptr[0] -> setdata(num);
return 0;
}
You just allocate the memory for the pointers (not for the objects), so ptr[0] points to an unspecified address and you get a segfault.
You need to add something like this:
for(int i = 0; i < 5; i++) {
ptr[i] = new dataClass;
}
When using a pointer-to-pointer-to-type, you must allocate storage for the required number of pointers and then allocate storage for each class which you then assign to each pointer.
For example, using 5 pointers as you attempt in your questions, you would first need to allocate for the pointers, e.g.
#define NPTRS 5
...
dataClass** ptrs = new dataClass *[NPTRS];
Now you have storage allocated for 5 pointers to type dataClass with the address for the initial pointer assigned to ptrs (I added the plural form for clarity)
The storage for the pointers is now allocated, but each of the allocated pointers does not yet point to valid storage for dataClass, they are just pointers. Before you can use the pointers to reference an instance of the class, you must allocate storage for each each class instance and then assign the address of the new block of memory to each of your pointers, e.g.
for (int i = 0; i < NPTRS; i++) {
ptrs[i] = new dataClass;
ptrs[i]->setdata (i+1);
}
(above you allocate storage for each class instance assigning the result to ptrs[i] and then set the data value to i+1)
Putting it altogether, you could do something similar to:
#include <iostream>
#include <cstdlib>
#define NPTRS 5
class dataClass {
int data;
public:
void setdata(int d) {data = d;}
int getdata() const {return data;}
};
int main() {
dataClass** ptrs = new dataClass *[NPTRS];
for (int i = 0; i < NPTRS; i++) {
ptrs[i] = new dataClass;
ptrs[i]->setdata (i+1);
}
for (int i = 0; i < NPTRS; i++)
std::cout << "ptrs[" << i <<"]->getdata() : "
<< ptrs[i]->getdata() << '\n';
return 0;
}
(note: don't forget you are responsible for keeping track of what you allocated and calling delete to free each allocation when it is not longer needed)
Example Use/Output
$ ./bin/dblptr2class
ptrs[0]->getdata() : 1
ptrs[1]->getdata() : 2
ptrs[2]->getdata() : 3
ptrs[3]->getdata() : 4
ptrs[4]->getdata() : 5
As others have mentioned, the C++ containers like vector are for less error prone and make your job a lot easier. Still, you should know how to handle both new/delete as well as the use of the containers.
Look things over and let me know if you have further questions.
You could first create an array of objects
(constructors will be called automatically).
After that create a pointer to your pointer:
#include <stdio.h>
class dataClass {
int data;
public:
dataClass(){
printf(" new instance \n");
}
void setdata(int d) {
data = d;
printf(" setdata \n");
}
int getdata() const {return data;}
};
int main() {
dataClass* ptr = new dataClass[5];
dataClass** pptr = &ptr;
int num = 9;
pptr[0]->setdata(num);
return 0;
}
result:
new instance
new instance
new instance
new instance
new instance
setdata

How can I return this 2d array? [duplicate]

How can I return an array from a method, and how must I declare it?
int[] test(void); // ??
int* test();
but it would be "more C++" to use vectors:
std::vector< int > test();
EDIT
I'll clarify some point. Since you mentioned C++, I'll go with new[] and delete[] operators, but it's the same with malloc/free.
In the first case, you'll write something like:
int* test() {
return new int[size_needed];
}
but it's not a nice idea because your function's client doesn't really know the size of the array you are returning, although the client can safely deallocate it with a call to delete[].
int* theArray = test();
for (size_t i; i < ???; ++i) { // I don't know what is the array size!
// ...
}
delete[] theArray; // ok.
A better signature would be this one:
int* test(size_t& arraySize) {
array_size = 10;
return new int[array_size];
}
And your client code would now be:
size_t theSize = 0;
int* theArray = test(theSize);
for (size_t i; i < theSize; ++i) { // now I can safely iterate the array
// ...
}
delete[] theArray; // still ok.
Since this is C++, std::vector<T> is a widely-used solution:
std::vector<int> test() {
std::vector<int> vector(10);
return vector;
}
Now you don't have to call delete[], since it will be handled by the object, and you can safely iterate it with:
std::vector<int> v = test();
std::vector<int>::iterator it = v.begin();
for (; it != v.end(); ++it) {
// do your things
}
which is easier and safer.
how can i return a array in a c++ method and how must i declare it? int[] test(void); ??
This sounds like a simple question, but in C++ you have quite a few options. Firstly, you should prefer...
std::vector<>, which grows dynamically to however many elements you encounter at runtime, or
std::array<> (introduced with C++11), which always stores a number of elements specified at compile time,
...as they manage memory for you, ensuring correct behaviour and simplifying things considerably:
std::vector<int> fn()
{
std::vector<int> x;
x.push_back(10);
return x;
}
std::array<int, 2> fn2() // C++11
{
return {3, 4};
}
void caller()
{
std::vector<int> a = fn();
const std::vector<int>& b = fn(); // extend lifetime but read-only
// b valid until scope exit/return
std::array<int, 2> c = fn2();
const std::array<int, 2>& d = fn2();
}
The practice of creating a const reference to the returned data can sometimes avoid a copy, but normally you can just rely on Return Value Optimisation, or - for vector but not array - move semantics (introduced with C++11).
If you really want to use an inbuilt array (as distinct from the Standard library class called array mentioned above), one way is for the caller to reserve space and tell the function to use it:
void fn(int x[], int n)
{
for (int i = 0; i < n; ++i)
x[i] = n;
}
void caller()
{
// local space on the stack - destroyed when caller() returns
int x[10];
fn(x, sizeof x / sizeof x[0]);
// or, use the heap, lives until delete[](p) called...
int* p = new int[10];
fn(p, 10);
}
Another option is to wrap the array in a structure, which - unlike raw arrays - are legal to return by value from a function:
struct X
{
int x[10];
};
X fn()
{
X x;
x.x[0] = 10;
// ...
return x;
}
void caller()
{
X x = fn();
}
Starting with the above, if you're stuck using C++03 you might want to generalise it into something closer to the C++11 std::array:
template <typename T, size_t N>
struct array
{
T& operator[](size_t n) { return x[n]; }
const T& operator[](size_t n) const { return x[n]; }
size_t size() const { return N; }
// iterators, constructors etc....
private:
T x[N];
};
Another option is to have the called function allocate memory on the heap:
int* fn()
{
int* p = new int[2];
p[0] = 0;
p[1] = 1;
return p;
}
void caller()
{
int* p = fn();
// use p...
delete[] p;
}
To help simplify the management of heap objects, many C++ programmers use "smart pointers" that ensure deletion when the pointer(s) to the object leave their scopes. With C++11:
std::shared_ptr<int> p(new int[2], [](int* p) { delete[] p; } );
std::unique_ptr<int[]> p(new int[3]);
If you're stuck on C++03, the best option is to see if the boost library is available on your machine: it provides boost::shared_array.
Yet another option is to have some static memory reserved by fn(), though this is NOT THREAD SAFE, and means each call to fn() overwrites the data seen by anyone keeping pointers from previous calls. That said, it can be convenient (and fast) for simple single-threaded code.
int* fn(int n)
{
static int x[2]; // clobbered by each call to fn()
x[0] = n;
x[1] = n + 1;
return x; // every call to fn() returns a pointer to the same static x memory
}
void caller()
{
int* p = fn(3);
// use p, hoping no other thread calls fn() meanwhile and clobbers the values...
// no clean up necessary...
}
It is not possible to return an array from a C++ function. 8.3.5[dcl.fct]/6:
Functions shall not have a return type of type array or function[...]
Most commonly chosen alternatives are to return a value of class type where that class contains an array, e.g.
struct ArrayHolder
{
int array[10];
};
ArrayHolder test();
Or to return a pointer to the first element of a statically or dynamically allocated array, the documentation must indicate to the user whether he needs to (and if so how he should) deallocate the array that the returned pointer points to.
E.g.
int* test2()
{
return new int[10];
}
int* test3()
{
static int array[10];
return array;
}
While it is possible to return a reference or a pointer to an array, it's exceedingly rare as it is a more complex syntax with no practical advantage over any of the above methods.
int (&test4())[10]
{
static int array[10];
return array;
}
int (*test5())[10]
{
static int array[10];
return &array;
}
Well if you want to return your array from a function you must make sure that the values are not stored on the stack as they will be gone when you leave the function.
So either make your array static or allocate the memory (or pass it in but your initial attempt is with a void parameter). For your method I would define it like this:
int *gnabber(){
static int foo[] = {1,2,3}
return foo;
}
"how can i return a array in a c++ method and how must i declare it?
int[] test(void); ??"
template <class X>
class Array
{
X *m_data;
int m_size;
public:
// there constructor, destructor, some methods
int Get(X* &_null_pointer)
{
if(!_null_pointer)
{
_null_pointer = new X [m_size];
memcpy(_null_pointer, m_data, m_size * sizeof(X));
return m_size;
}
return 0;
}
};
just for int
class IntArray
{
int *m_data;
int m_size;
public:
// there constructor, destructor, some methods
int Get(int* &_null_pointer)
{
if(!_null_pointer)
{
_null_pointer = new int [m_size];
memcpy(_null_pointer, m_data, m_size * sizeof(int));
return m_size;
}
return 0;
}
};
example
Array<float> array;
float *n_data = NULL;
int data_size;
if(data_size = array.Get(n_data))
{ // work with array }
delete [] n_data;
example for int
IntArray array;
int *n_data = NULL;
int data_size;
if(data_size = array.Get(n_data))
{ // work with array }
delete [] n_data;

How to pass an Array into a Class in C++

When i create a class I would like to be able to store an array in that class. Is this possible?
For example. If i have a class called array to store an array from my main function
int main()
{
double nums[3] = {1 2 3}
array Vnums(nums)
return 0
}
class array
{
public
//constructor
array(double nums[])
{
double vector[] = nums;
}// end constructor
}// end array
Thank you!
use a std::array instead of a raw array. It's just like a raw array, but copiable, and has useful member functions.
class array
{
std::array<double, 3> classArray;
public:
//constructor
explicit array(const std::array<double, 3>& rhs)
:classArray(rhs)
{}// end constructor
}// end array
int main()
{
std::array<double, 3> nums = {{1 2 3}};
array Vnums(nums)
return 0
}
or maybe a std::vector if you want to be able to change the size at will
class array
{
std::vector<double> classArray;
public:
//constructor
explicit array(const std::vector<double>& rhs)
:classArray(rhs)
{}// end constructor
}// end array
int main()
{
std::vector<double> nums{1 2 3}; //C++11 feature
array Vnums(nums)
return 0
}
I'm not sure what you're doing, so it's hard to give solid advice. You can pass a raw array by reference, a pointer and a count, an iterator pair...
Yes, but you must either allocate the array dynamically upon class creation, or the array must always be the same size.
Option A:
class array{
private:
double* data;
unsigned size;
public:
array(double* d, unsigned s){
size = s;
data = new double[size];
for(unsigned i = 0; i < s; i++)
data[i]=d[i];
}
array(const array& copy){
double* temp = new double[copy.size];
delete [] data;
data = temp;
size = copy.size;
for(unsigned i = 0; i < size; i++)
temp[i]=copy.data[i];
}
array& operator= (const array& copy){
double* temp = new double[copy.size];
delete [] data;
data = temp;
size = copy.size;
for(unsigned i = 0; i < size; i++) data[i]=copy.data[i];
}
~array(){
delete[] data; // Don't forget the destructor!
}
};
This is probably the way you need, but note that you will almost certainly need the custom copy constructor and assignment operator so that you don't share any memory between multiple instances of this class. A better way might be to make a copy function that both can use.
Option B:
class array{
private:
double data[3];
public:
array(double* d){ //or "double(&d)[3]" to be safer, but less flexible
for(unsigned i = 0; i < 3; i++){
data[i] = d[i]; // If d is not at least size 3, your program will crash here (or later on, or maybe just act in an undefined way)
}
}
}
Haven't tested this, but it should be an ok starting point.