MyClass *myVar;
myVar = new MyClass[num];
Actually in this form you cannot invoke constructor which takes parameter(s). It is not allowed by the language specification.
However, if you use std::vector, which I recommend you to use, then you can create a vector calling non-default constructor as:
#include <vector> //header file where std::vector is defined
std::vector<MyClass> arr(num, MyClass(10,20));
It creates a vector of num elements, each element is created by calling copy-constructor of the class, passing MyClass(10,20) as argument to it.
The vector is also good because now you dont need to manage memory yourself. Neither manual allocation, nor manual deallocation. Plus, you can know the number of elements by calling arr.size() anytime. You always know how many elements the vector contains. You can also add elements anytime, just by calling .push_back() member function as:
arr.push_back(MyClass(20,30));
And now you can access elements, just like you access array, i.e by using index:
f(arr[i]); // 0 <= i < arr.size();
Additionally, you can use iterators which facilitate idiomatic programming, enabling you to use various algorithmic functions from <algorithm> header as:
#include <algorithm> //header file where std::for_each is defined
std::for_each(arr.begin(), arr.end(), f);
where f is function which takes one argument of type MyClass& (or MyClass const &) depending on what you want to do in f.
In C++11, you can use lambda as:
std::for_each(arr.begin(), arr.end(),
{
//working with m
});
Answer from Sarfaraz Nawaz on Stack OverflowMyClass *myVar;
myVar = new MyClass[num];
Actually in this form you cannot invoke constructor which takes parameter(s). It is not allowed by the language specification.
However, if you use std::vector, which I recommend you to use, then you can create a vector calling non-default constructor as:
#include <vector> //header file where std::vector is defined
std::vector<MyClass> arr(num, MyClass(10,20));
It creates a vector of num elements, each element is created by calling copy-constructor of the class, passing MyClass(10,20) as argument to it.
The vector is also good because now you dont need to manage memory yourself. Neither manual allocation, nor manual deallocation. Plus, you can know the number of elements by calling arr.size() anytime. You always know how many elements the vector contains. You can also add elements anytime, just by calling .push_back() member function as:
arr.push_back(MyClass(20,30));
And now you can access elements, just like you access array, i.e by using index:
f(arr[i]); // 0 <= i < arr.size();
Additionally, you can use iterators which facilitate idiomatic programming, enabling you to use various algorithmic functions from <algorithm> header as:
#include <algorithm> //header file where std::for_each is defined
std::for_each(arr.begin(), arr.end(), f);
where f is function which takes one argument of type MyClass& (or MyClass const &) depending on what you want to do in f.
In C++11, you can use lambda as:
std::for_each(arr.begin(), arr.end(),
{
//working with m
});
In C++0x, this grammar works, which can call the non-default constructor in new expression:
MyClass *myVar;
myVar = new MyClass[2]{{10, 20},{20, 30}};
But I doubt if it works when the number of elements in available only at run time.
The vector approach would be better, as shown in Nawaz's answer.
c++ - Dynamic arrays inside a class - Stack Overflow
copy constructor - c++ dynamic arrays in class - Stack Overflow
c++ - How do I initialize a dynamically allocated array within a class constructor - Stack Overflow
C++ copy constructor for class with dynamically allocated array - Stack Overflow
In your constructors, you're defining a local variable
double * matrix = new double[N * N];
which shadows your member variable of the same name, so the member is never initialised.
All you should need is to change it to
matrix = new double[N * N];
And it's very un-C++ to use this-> for member access unless it's absolutely necessary for disambiguation (which is almost never)
You will find more "C++" (and sometime the only way to initialize members):
Matrix::Matrix(int M, int N): rows (M),
columns (N),
matrix (new double[M * N])
{
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
matrix[i * N + j] = 0;
}
Now try to understand this:
Matrix::Matrix( int N): rows (N),
columns (N),
matrix (new double[N * N])
{
for(int i = 0; i < N; i++)
for(int j = 0; j < N; j++)
matrix[i * N + j] = (i==j);
}
If you use:
class Matrix{
private:
int rows;
int columns;
std::unique_ptr<double[]> matrix;
you will find that you dont need a destructor, and some other inerest thing. Also, read my other answer.
new int(10) makes an int variable with the value 10. new int[10] makes an array of 10 ints. From the context, it's clear that you intended to use the second form. The use of the first form would lead to undefined behavior when you called delete[] values; (since values would not be an array) or when you accessed any elements beyond the first.
When you're allocating arrays you should do int *newvalues = new int[ntests+1]; using brackets instead []
You should allocate memory before using dynamic array.I have allocated memory for b
class A //in a.h
{
private:
B * b;
int maxNumberOfItems;
//...
public:
A();
~A();
void addB(const B & something);
};
//in a.cpp
A::A()
{
maxNumberOfItems=10;
b = new B[maxNumberOfItems];
for(int i=0;i<maxNumberOfItems;i++)
{
b[i]="";//has to be an empty string, I am getting a segmentation fault
}
}
A::~A(){/*...*/}
//...
//in b.h
class B
{
private:
string name;
int price;
public:
void setName(string);
string getName();
void setPrice();
int getPrice(int);
B & operator=(string &);
};
//in b.cpp
B & B::operator=(string & a){name = a;price = 0; return *this;}
It looks like class A is supposed to be a dynamic array class.
When you create a new instance of A you must also allocate memory for your array b. Which is just a pointer to some point in memory. From the code you posted, it doesn't get initialized and can point to any random memory place -- which is not good (i.e. the likely cause of your segfault).
I'd suggest making the following change.
A::A(){
maxNumberOfItems=10;
b = new B[maxNumberOfItems]; // b is an array of B objects.
// with default constructed values
// This way avoids the need for using a for loop and reassigning values
}
~A(){
if (b != NULL) { delete b; }
}
class B{
private:
//....
public:
B(): name(""), price(0) {}
// Although the default constructor without defining one should behave the same.
// This just makes it explicit. what name and price default to.
}
This:
Array::Array( const Array & obj )
{
_arr = new int[_size];
for(int i=0;i<_size;i++)
*_arr[i] = *obj._arr[i];
}
could be this:
Array::Array( const Array & obj )
: _arr(obj._size ? new int[obj._size] : nullptr)
, _size(obj._size)
{
if (_arr)
std::copy(obj._arr, obj._arr+_size, _arr);
}
Specifically, note the use of the initializer list. Other things worth mentioning:
Don't use identifiers with leading underscores. Besides making the code a royal pain to read, you can quickly find yourself using identifiers that are reserved by the implementation. That isn't the case here, but I'm willing to bet that wasn't by intent.
You also need an assignment operator to fulfill the Rule of Three. Thankfully, a decent copy constructor makes that trivial.
Don't do any of this. This is why, with great wailing and much gnashing of teeth in design decisions, the almighty C++ standards committees of years-gone-by have so-chosen to bless us with
std::vector<>. If you're doing this to learn, good. What you'll eventually learn is how rarely you need to once you embrace the standard library and all its guilty pleasures.
If this is intended as a learning exercise, kudos, and blissfully ignore (3) above. For (2), you can use the copy/swap idiom now that you have a reasonable copy-ctor:
Array& Array::operator =(Array obj) // value-param intentional
{
std::swap(_arr, obj._arr);
std::swap(_size, obj._size);
return *this;
}
Best of luck.
_size has no initial values, since you have not passed it either as arguements or initialized anywhere else before using it.
Also, don't do *_arr[i] = *obj._arr[i];
It doesn't make sense as arr[i] itself means *(arr+i).
Do:
_arr[i] = obj._arr[i];
This is wrong on a number of levels. First in the class declaration:
char content[];
That gives you a pointer to an array of zero length.
This gives you an array of char, of zero length. This is not useful.
char* content = new char[_len];
content = _chars;
That does a new into a new variable content - not the class variable. Then you assign (overwrite) the passed pointer into content (discarding the memory you just allocated). That pointer is then discarded when the constructor ends. Perhaps using strcpy would be better.
I made up a small example based on your code which prints the correct result:
class bufr
{
public:
//constructor and deconstructor
bufr(char* chars, uint8_t len);
~bufr();
//variables
uint8_t len_;
char * content_;
}; // end of class bufr
bufr::bufr(char* chars, uint8_t len)
{
content_ = new char[len];
memcpy (content_, chars, len); // copy into allocated memory
len_ = len; // remember length
} // end of constructor
bufr::~bufr()
{
delete [] content_;
} // end of destructor
void setup()
{
Serial.begin (115200);
char chars[] = "1234 ";
bufr buf(chars, sizeof chars);
Serial.println (buf.content_);
} // end of setup
void loop()
{
} // end of loop
Can you explain to me why it was making a new variable content and not using the class variable?
Small example:
char * content;
void loop ()
{
char * content = "foo"; // makes a NEW variable
}
In this example there are two variables named content. The one in the function "shadows" the global one. However the code below only has one variable:
char * content;
void loop ()
{
content = "foo"; // uses existing variable
}
In the destructor, when you delete the pointer to the array, does this free up the memory allocated to the array? It's now free to be assigned again by something else? Or does it sit there still initialized as that array, not being able to be used again?
You aren't deleting the pointer. You are deleting the memory it points to. The pointer is now pointing to freed memory, so using it as a pointer at this stage would be wrong. You can do another new to make it point to something else.
they delete pointer and then delete[] pointer.
You misinterpreted that. You either delete pointer or delete [] pointer depending on whether pointer is an array or not. I reworked content to not be an array, thus deleting it without the brackets is correct however as it is allocated using new [] it must be deleted with delete [].
on the link posted above they say to use delete this way: delete pointer if it was a single element allocated with new or delete [] pointer to release memory allocation for arrays of elements allocated with new and a size in []'s. So in my case I want to use delete [] content_?
No, you don't want to be setting up an array in the first place. Take a look at this small example:
struct {
char bar [];
} foo;
void setup()
{
Serial.begin (115200);
Serial.println ("Starting");
Serial.println (sizeof (foo));
Serial.println (sizeof (foo.bar));
}
void loop()
{
}
That prints:
Starting
0
0
The variable bar is a zero-length array. Thus the entire struct foo is also zero length. It isn't even a pointer (that would be two bytes on this platform).
It is wrong to use an array of char like that, when you want to dynamically allocate memory. Look at this:
char foo [4];
That allocates 4 bytes of memory for foo. You can't later on make it longer by doing a new.
What you want is:
char * foo;
Now you have allocated a pointer and can do a new, like this:
foo = new char [10]; // allocate 10 bytes
And then delete it:
delete [] foo;
You use the brackets on the delete, as you used them with the new.
If you allocated one char you wouldn't use brackets. eg.
char * foo;
foo = new char; // allocate a pointer to one byte
...
delete foo;
Many programmers have a disjoint between a pointer and an array. Here's an explanation.
Here is a variable of type char, initialised with the value 'A':
char c = 'A';
'A' has the ASCII value of 65, so that means that there's a byte in memory that holds the value 65. Let's say that byte in memory is at address 0x2000. If you were to add 1 to that byte, it would become 66, and if you were to print it as a character, it would print B (ASCII 66).
Here is a pointer to a char, initialised with the address in memory of c:
char *p_c = &c; // Get the address of c into p_c
[Note that
char *p_c = c;would be invalid: you can't initialise a pointer with achar! That'd givep_cthe value65- not what you want!]
In Arduino, p_c represents two successive bytes of memory that together store the address of a char: in this case the value 0x2000. Where those two bytes are doesn't matter for this explanation - but trust that they too have an address...
If you were to change c into a 'Z', that would change c's contents, but not p_c's (it would still be 0x2000). But if you were to use p_c to look at the byte it was pointing to (c), then you'd see the 'Z'.
- If you were to do a
printf("%c", c);you'd get a 'Z'.%cmeans "I've got a character as the next variable in theprintf()list". - If you were to do a
printf("%c", *p_c);you'd also get a 'Z'. - If you were to do a
printf("%c", p_c);you'd get horrible results.You lied to
printf()- you didn't give it a one-byte character, you gave it a two-byte pointer!
Now let's move on to arrays.
Here is a variable of type char [], initialised with the value "John".
char s[] = "John";
'J' has the ASCII value 74, 'o' 112, 'h' 104, and 'n' 111. That means that in memory there are four sequential bytes with the values 74, 112, 104, 111. Let's say that those bytes are at addresses 0x3000 through 0x3003.
And here is another pointer to char, this time initialised with the address in memory of s.
char *p_s = s; // Point to s with p_s
I hate that the C language allows the above. It is one of the roots of the whole array/pointer confusion. It kind-of implies that
p_ssomehow gets all of"John"assigned to it. Nope!
A better statement would have been:
char *p_s = &s; // Initialise p_s with the address of s // ILLEGAL!
That gives a MUCH better idea of what's happening - alas, it's not how it's done...
But also note that neither of the above could possibly store 0x3000-0x3003 (the addresses for all of s), so they have to be satisfied with only storing the start of the string: p_s will get the value 0x3000.
Note that s does NOT have the value 0x3000 in it. That is its address, like 0x2000 was c's address (it too doesn't have 0x2000 in it). But p_s does have 0x3000 in it - and don’t forget that p_s also has its own address (I won't bother with that here).
And this is where the "equivalency" (they're not) between a pointer and an array starts to get people confused:
s[2] = 'h';andp_s[2] = 'h';do the same thing - but in different ways!- The first accesses
0x3002directly. - The second needs to find out that
p_sis0x3000and add2to it before it can access0x3002.
- The first accesses
*(p_s + 2) = 'h';is yet a third way to do the same thing.
So now let's printf() these new variables:
printf("%c", *s);wouldn’t compile.sis not a pointer, so you can’t dereference it with*.printf("%c", *p_s);would print the character at wherep_swas pointing.This would print out
J.printf("%c", s[0]);would print the character ats[0].This would print out
J.printf("%c", s);would give horrible results.Again, you lied to
printf()!printf("%s", s);would work (but see below).%smeans "I've got a sequence of characters that I'd like you to print. I've provided the address of the first character."printf("%s", p_s);would be identical to the previous one.After all, the same address value was passed!
printf("%s", *p_s);would give horrible results.Again, you lied to
printf()!
But note something: you've given printf() the beginning of the string, so it can start printing. How does printf() know where the end of the string is? You didn't provide the number 4; it's not stored anywhere; how can it know when to stop?
That's where a C convention for strings steps in. By convention, when the compiler sees a string "between quotes", it stores the ASCII values of the characters, and then follows them with a 0. Not an ASCII '0' (with value 48), but an ASCII NUL (with value 0). Thus if you looked at address 0x3004 (the byte directly after John), you'd see a 0 in that memory byte. That's how printf() knows to stop printing - and yes, many a bug has resulted from forgetting to maintain a NUL at the end of a sequence of chars!
That then leads me to the sizeof() function
sizeof() always returns a constant at compile time using information that the compiler then knows about:
sizeof(c)would return1.sizeof(p_c)would return2.sizeof(p_s)would also return2.It is after all merely a pointer too.
sizeof(*p_c)would return1.sizeof(*p_s)would also return1.It's only pointing to a single char...
sizeof(s)would return5.The compiler knows what
sis: an array of 5 bytes (including the finalNUL).- Given a pointer, there is no (native) way to find out how large the buffer it is pointing to can be.
OK: so if you've got a char [] you can find out its size. Note that that is its maximum size - the string inside it could be a lot shorter! If you did the following:
s[3] = 0; // Overwrite the fourth character (arrays start at 0)
printf("%s", s);
[Note a better version of the first line would be
s[3] = '\0';which means "store the ASCII character0(NOT'0')" instead of "store the number0".]
you'd get Joh printed out. Note:
sizeof(s)remains5;- You can't get the length with
sizeof(*p_s); - The string inside it is only 3 characters long.
So... if you've got a string buffer, or a pointer to one, how do you know how long it is? Count the number of characters until you reach a NUL - and there's already a function to do that for you: strlen().
Which now leads to the final point about pointers: dynamic allocation of memory.
The array s above was sized by the compiler at compile time: it could count the characters, add one for the NUL, and reserve the right number of bytes. You could also have written:
char s[10] = "John";
which would have reserved 10 bytes and only initialised the first 5 of them. The following would be an error:
char s[3] = "John"; // Buffer too small!
Scarily,
char s[4] = "John";works... (The compiler says to itself "No room for theNUL?! Ah well...”) Better never pass that string tostrlen()orprintf()then!
What if you don't know at compile time how big a string is going to be? If you know at runtime, you can ask the system for a lump of memory from the heap - a reserved area that can have chunks taken from it and returned as required. There are two ways to do this:
char *p_b = (char *)malloc(size); // Where size is a variable
char *buffer = new char[size]; // Grab 'size' new chars
The first calls malloc(), passing in the number of desired bytes. If malloc() can give those bytes it will reserve them and return a pointer to them. If it can't it will return 0. You should always test the return value! If not, you'll corrupt things horribly...
The second uses the more sophisticated new[] syntax, which is more object oriented. Notice how malloc()'s return value needed to be turned into a (char *)? That's because it doesn't know what type of pointer it's returning, so it just picks void *. new does know, so it returns the correct type - but it still may return 0 if there's no room!
Once you've got either pointer, you use them just like p_s before. There is nothing stopping you from accessing outside the boundaries of the buffer - just like there isn't for p_s! Be careful!
Oh, and once you've finished with the lump of memory, you need to return it to the heap:
free(p_b);
delete [] buffer;
If you used malloc(), return it with free(). If you used new[], return it with delete[].
And all of the above is why they invented the String object.
It manages the memory; keeps track of the string's length; lets you access and modify individual characters; lets you resize the string as needed; and gets rid of the used memory once you're finished with it. No wonder people start to use String syntax when they see string pointers...
But Strings are only useful for chars. Arrays and pointers can be of and to anything - including Strings and (GASP!) pointers! Uh oh - here we go again...
type _mArray[size] = new type[size];
The template instantiates with: type is int, and size is 2. Therefore, this becomes:
int _mArray[2] = new int[2];
This obviously does not make much sense. If you put this, verbatim, in your main() your C++ compiler will also serve you with the same complaint.
It's clear that the intent here is, simply:
type _mArray[size];
And nothing else.
P.S. Now, let's go back and reread what the suffering C++ compiler was struggling to communicate here:
Array initializer must be an initializer list
int _mArray[2] is, obviously, an array. There's an = stuck after it. Ok, this must be array initialization. How do you initialize an array in C++? With a braced initialization list, of course. This would be something like this, for example:
int _mArray[2]={1, 2};
The C++ compiler saw nothing of that kind, and was trying to tell you that.
#include<iostream>
template<typename type, int size>
class Array
{
private:
type * _mArray ;
public:
int Access(int index)
{
return _mArray[index];
}
int Len()
{
return size;
}
Array()
{
_mArray = new type[size];
}
~Array()
{
delete[] _mArray;
}
int& operator{
return _mArray[index];
}
};//All code above compiles successfully
int main()
{
Array<int, 2> name;
name[0] = 1024;
name[1] = 100;
for(int i= 0; i< name.Len(); i++)
{
std::cout<< name[i] << std::endl;
}
}
For building containers you obviously want to use one of the standard containers (such as a std::vector). But this is a perfect example of the things you need to consider when your object contains RAW pointers.
If your object has a RAW pointer then you need to remember the rule of 3 (now the rule of 5 in C++11).
- Constructor
- Destructor
- Copy Constructor
- Assignment Operator
- Move Constructor (C++11)
- Move Assignment (C++11)
This is because if not defined the compiler will generate its own version of these methods (see below). The compiler generated versions are not always useful when dealing with RAW pointers.
The copy constructor is the hard one to get correct (it's non trivial if you want to provide the strong exception guarantee). The Assignment operator can be defined in terms of the Copy Constructor as you can use the copy and swap idiom internally.
See below for full details on the absolute minimum for a class containing a pointer to an array of integers.
Knowing that it is non trivial to get it correct you should consider using std::vector rather than a pointer to an array of integers. The vector is easy to use (and expand) and covers all the problems associated with exceptions. Compare the following class with the definition of A below.
class A
{
std::vector<int> mArray;
public:
A(){}
A(size_t s) :mArray(s) {}
};
Looking at your problem:
A* arrayOfAs = new A[5];
for (int i = 0; i < 5; ++i)
{
// As you surmised the problem is on this line.
arrayOfAs[i] = A(3);
// What is happening:
// 1) A(3) Build your A object (fine)
// 2) A::operator=(A const&) is called to assign the value
// onto the result of the array access. Because you did
// not define this operator the compiler generated one is
// used.
}
The compiler generated assignment operator is fine for nearly all situations, but when RAW pointers are in play you need to pay attention. In your case it is causing a problem because of the shallow copy problem. You have ended up with two objects that contain pointers to the same piece of memory. When the A(3) goes out of scope at the end of the loop it calls delete [] on its pointer. Thus the other object (in the array) now contains a pointer to memory that has been returned to the system.
The compiler generated copy constructor; copies each member variable by using that members copy constructor. For pointers this just means the pointer value is copied from the source object to the destination object (hence shallow copy).
The compiler generated assignment operator; copies each member variable by using that members assignment operator. For pointers this just means the pointer value is copied from the source object to the destination object (hence shallow copy).
So the minimum for a class that contains a pointer:
class A
{
size_t mSize;
int* mArray;
public:
// Simple constructor/destructor are obvious.
A(size_t s = 0) {mSize=s;mArray = new int[mSize];}
~A() {delete [] mArray;}
// Copy constructor needs more work
A(A const& copy)
{
mSize = copy.mSize;
mArray = new int[copy.mSize];
// Don't need to worry about copying integers.
// But if the object has a copy constructor then
// it would also need to worry about throws from the copy constructor.
std::copy(©.mArray[0],©.mArray[c.mSize],mArray);
}
// Define assignment operator in terms of the copy constructor
// Modified: There is a slight twist to the copy swap idiom, that you can
// Remove the manual copy made by passing the rhs by value thus
// providing an implicit copy generated by the compiler.
A& operator=(A rhs) // Pass by value (thus generating a copy)
{
rhs.swap(*this); // Now swap data with the copy.
// The rhs parameter will delete the array when it
// goes out of scope at the end of the function
return *this;
}
void swap(A& s) noexcept
{
using std::swap;
swap(this.mArray,s.mArray);
swap(this.mSize ,s.mSize);
}
// C++11
A(A&& src) noexcept
: mSize(0)
, mArray(NULL)
{
src.swap(*this);
}
A& operator=(A&& src) noexcept
{
src.swap(*this); // You are moving the state of the src object
// into this one. The state of the src object
// after the move must be valid but indeterminate.
//
// The easiest way to do this is to swap the states
// of the two objects.
//
// Note: Doing any operation on src after a move
// is risky (apart from destroy) until you put it
// into a specific state. Your object should have
// appropriate methods for this.
//
// Example: Assignment (operator = should work).
// std::vector() has clear() which sets
// a specific state without needing to
// know the current state.
return *this;
}
}
I'd recommend using std::vector: something like
typedef std::vector<int> A;
typedef std::vector<A> AS;
There's nothing wrong with the slight overkill of STL, and you'll be able to spend more time implementing the specific features of your app instead of reinventing the bicycle.
I'm trying to write a dynamic array implementation of my own. This is what I have so far:
template <typename T>
class dynamic_array
{
private:
T* data;
int capacity;
int size{};
bool isFull()
{
return size == capacity;
}
bool inBounds(int index)
{
return (index > 0 && index < size);
}
void extend()
{
// TODO:
}
public:
dynamic_array(int size)
: capacity{ size }, data{ new T[size] {} }
{
}
void push(T item)
{
if (isFull())
extend();
else
data[size++] = item;
}
T get(int index)
{
if (inBounds(index))
return data[index];
}
int length() { return size; }
};
I was wondering if someone could help me out on the extend method. I was wondering if I needed to explicitly deallocate the memory that was allocated for the original data array. So in other words, I'm wondering if the extend method should look like this:
void extend()
{
capacity *= 2;
T* newData{ new T[capacity] {} };
for (int i{ 0 }; i < size; ++i)
newData[i] = data[i];
// explicitly deallocate old data
delete[] data;
// point data to newData
data = newData;
}Or if I could simply omit the delete statement:
void extend()
{
capacity *= 2;
T* newData{ new T[capacity] {} };
for (int i{ 0 }; i < size; ++i)
newData[i] = data[i];
// point data to newData
data = newData;
}Will the old data be deallocated automatically? I would think not since C++ doesn't use a garbage collector.