I'm trying to learn a little bit more of C++!
After working around with memory allocation for a while I got to a place where I'm struggling to understand it.
I wrote a code that works well (not really sure of that but at least doesn't show any memory violation) for a type of initialization (of an object of some class) but it crashes for a similar initialization.
I would appreciate if someone could me explain what is happening and how can I solve this problem.
My thought: The problem is in the line bellow because I'm trying to delete an array of allocated objects when in the problematic initialization I only have one object allocated and not an array.
delete[] pointer; //PROBLEMATIC LINE
PS.: I'm not looking for alternative solutions (like using smart-pointers or whatever). Sorry for my English!
The code:
class class1
{
private:
unsigned int s;
double* pointer;
public:
/* Constructors */
class1() { s = 0; pointer = nullptr; }
class1(unsigned int us, double* uarray)
{
pointer = new double[us];
for (unsigned int i = 0; i < us; i++)
pointer[i] = uarray[i];
}
class1(const class1& other)
{
pointer = new double[s];
for (unsigned int i = 0; i < s; i++)
pointer[i] = other.pointer[i];
}
~class1() { if (!s && pointer != nullptr) delete[] pointer; }
public:
/* Operators Overloading */
class1& operator=(const class1& other)
{
s = other.s;
pointer = new double[s];
for (unsigned int i = 0; i < s; i++)
pointer[i] = other.pointer[i];
return *this;
}
};
class class2
{
private:
unsigned int m;
unsigned int n;
class1* pointer;
public:
/* Constructors */
class2(unsigned int un, double* uarray, bool flag = false) : n(un)
{
m = 1;
pointer = new class1(un, uarray);
if (flag) { this->function(); }
}
~class2() { if (!m && !n) delete[] pointer; }
public:
/* Public Methods */
void function()
{
class1* newpointer = new class1[n];
//**... some code (when commented show the same error)**
delete[] pointer; //**PROBLEMATIC LINE**
pointer = newpointer;
}
public:
/*Template Constructor*/
template<unsigned int m, unsigned int n>
class2(unsigned int um, unsigned int un, double(&uarray)[m][n], bool flag = false) : m(um), n(un)
{
pointer = new class1[um];
for (unsigned int i = 0; i < um; i++)
{
class1 object1(un, uarray[i]);
pointer[i] = object1;
}
if (flag) { this->function(); }
}
};
int main()
{
double test3[] = { 1, 2, 3 };
double test4[][3] = { {3, 2, 1}, {6, 5, 4}, {9, 8, 7} };
double test5[][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
class2 m4(3, test3, true); //**NOT OK - VIOLATION OF MEMORY**
class2 m5(3, 3, test4, true); //**OK**
}
Your copy constructor for class1 is not setting the s member, but uses its indeterminate value here:
pointer = new double[s];
causing undefined behavior. Set s from other.s before using it.
Your second constructor has the same problem.
Your assignment operator of class1 is leaking memory, because it doesn't delete[] the previous array.
In class2 you use new in the non-array form, e.g. here:
pointer = new class1(un, uarray);
but in the destructor you call delete[] to delete pointer. This is also causing undefined behavior. Pointers returned from the non-array version of new need to be deleted by delete, e.g. delete pointer.
But since you are also using the array version of new for pointer, you cannot use delete pointer either. As using delete instead of delete[] on a pointer returned from a array-new has also undefined behavior.
Be consistent and use always the array-new, e.g.:
pointer = new class1[1]{{un, uarray}};
class2 causes undefined behavior when an object of its type is copied or moved, because you didn't implement a copy constructor and assignment operator although you have defined a destructor. This is a violation of the rule-of-three.
There is probably more that I missed. The code is not readable at all. Please use proper variable names next time. (I hope that the real code does not use this naming scheme...) E.g. having a non-type template parameter m with the same name as a member of that class and then using m in multiple places of that context is not ok. I had to check the lookup rules to make sure that this actually compiles and does something sensible.
Related
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 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 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 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;
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.