So I have the following code
class UserDB
{
private:
AccountInfo* _accounts[200] ; // store up to 200 accounts
public:
UserDB();
virtual ~UserDB();
}
UserDB::UserDB(){
//code for initializing it to null
}
UserDB::~UserDB(){
delete [] _accounts;
}
So basically I am trying to find this code to initialize _accounts to null but I cannot find a real answer, all the guides in the internet either say how to initialize an array, an object, or a pointer, but not something that is all three altogether, and even less how to initialize this kind of pointer to null, even whatever they are initializing [in the guides] looks very confusing, so I come once again to ask for help here.
Also, AccountInfo is just any random class.
use std::array or std::vector.
you don't delete[] _accounts because the array is a value -- it is an array of pointers. IOW, its size is not equal to a pointer.
Here's a std::vector approach:
class UserDB {
private:
std::vector<AccountInfo*> _accounts;
public:
UserDB() : _accounts(200, 0) {}
virtual ~UserDB() {}
};
However, you may prefer to use the vector's default initializer so you can use it to determine the number of accounts it holds.
Update in response to comments below:
Although there are reasons to hold an array of AccountInfo* pointers, you may also consider std::vector to hold an array of AccountInfos values:
class UserDB {
private:
std::vector<AccountInfo> _accounts;
public:
UserDB() : _accounts() {}
virtual ~UserDB() {}
void appendAccountInfo(const AccountInfo& info) {
this->_accounts.push_back(info);
}
};
std::vector will handle all your allocation and reallocation needs for you. It's also nice because it's dynamically resizable, and you won't be constrained to a fixed number of AccountInfos.
create a constant instead of the magic number 200 (not really necessary but it makes the code more readable and safer when later changing)
const int numberOfAccounts = 200;
AccountInfo* _accounts[numberOfAccounts]
UserDB::UserDB()
{
for (int i = 0; i < numberOfAccounts; ++i)
{
_accounts[i] = 0;
}
}
now you have you 200 zeroed pointers.
also have a habit of putting private members at the end of the class and public at the start,
especially by bigger classes you want to see the public stuff first, the private stuff you normally
don't want somebody to mess with.
class C
{
public:
protected:
private:
};
I do remember having read that this would work:
UserDB():_accounts(){}
This should initialize the contents to NULL
Related
Let's assume I got an abstract class ("Book" in the example below) and some derived classes ("ElectroniBook","CodingBook" in the example below). I also want to keep a vector of books in a third class ("Library") and some maps to find them. Let's also assume that I need to create the "Library" from somewhere else using the "addBook" method and then assign it in the main.
Since Book is abstract I eventually need to delete the "Book" pointers I created and I want to do it in some destructor. Neverthless, whenever I try to use delete i got this error message
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
and if I try to replace raw pointers with shared_pointers or unique_pointers I immediately get errors at compile time telling me I'm trying to use pointers that have already been deleted. Note that I'm using C++ 11.
Here's some code just for example :
class Book{
public:
Book(string name, int Npages);
virtual ~Book();
virtual void displayBook() = 0;
private:
string _name;
int _Npages;
}
class ElectronicBook : public Book{
public:
ElectronicBook(string name, int Npages);
~ElectronicBook();
void displayBook() { //do something
};
}
class CodingBook : public Book{
public:
CodingBook(string name, int Npages);
~CodingBook();
void displayBook() { // do something else
};
}
class Library{
public :
Library();
~Library(){
// this doesn't work for me
// for(auto & a : _books)
// delete a;
// _books.clear();
//
//for(int i=0;i<_bookmap.size();++i)
// delete bookmap.at(i);
};
void addCodingBook(string name, int Npages){
CodingBook* cb = new CodingBook(name, Npages);
_books.push_back(cb);
_bookmap[name] = cb;
//should I delete anything here?
};
void addEletronicBook(string name, int Npages){
ElectronicBook* eb = new ElectronicBook(name, Npages);
_books.push_back(eb);
_bookmap[name] = eb;
//should I delete anything here?
};
private :
vector<Book*> _books;
map<string, Book*> bookmap;
}
// separeted function
Library createLibrary(){
Library L;
while(...){
//read books from somewhere(file, input or whatever) and
// addElectronicBook(...)
// addCodingBook(...)
}
return L;
}
int main(){
Library myLibrary = createLibrary();
// do something with Library
}
Since I did several times "new" to add Books, I need to delete them. I tried to do it in the Library destructor like I showed but I got the error mentioned before.
If I understand correctly your issue, you are freeing twice the same memory:
// for(auto & a : _books)
// delete a;
// _books.clear();
//
//for(int i=0;i<_bookmap.size();++i)
// delete bookmap.at(i);
Both _books and bookmap contain pointers that are pointing to the same ares of memory and you are freeing them twice.
When working with raw pointers you have to decide who is the owner of the memory, say, for example _books and who has simply access to the memory but is not responsible for the cleanup.
So, you should:
delete only once, so use only one of the two for loops, say for the sake of argument _books
make sure that the other non-owning structures, say bookmap in our example, never, ever access the memory (i.e. de-reference the pointer) after the deletion
Suggestion: put in the vector unique_ptr so the vector is the owner and put raw pointers in the map to signal that the map is not owning. unique_ptr will take care of cleaning up the memory for you. If you want to be sure, add some print statements or put break points in the destructors if you have a debugger.
So, I have an array of a class called "Customer"
Customer** customersarray[] = new Customer*[customer];
I'm receiving int customer with cin.
anyways, in customer.cpp, there is a method called void deactivate().
which goes like this:
void Custmoer::deactivate()
{
if (this != NULL)
remove this;
//this = NULL; I want to do this but it doesn't work.
}
and the purpose of this is to remove it from customer array when satisfies a certain condition. So for example,
for (int i = customer - 1; i >= 0; i--)
{
if (customersarray[i]->getAngerLevel() == 5) {
customersarray[i]->deactivate();
}
for (int z = i; i < customer - 1; i++) {
*(customersarray + z) = *(customersarray + z + 1);
}
customer--;
}
so my first questions are:
why does this = NULL not work?
is there a simpler way to remove something from pointer array when a condition is satisfied? (for example, remove all customers that has anger level of 5.)
Your mistake is thinking that you can remove something from a Customer* array by some magic inside the Customer class, but that's not true. Just remove a customer from the customer array where ever the customer array is. For instance using remove_if
#include <algorithm>
Customer** customersarray = new Customer*[customer];
...
customer = std::remove_if(customersarray, customersarray + customer,
[](Customer* c) { return c->anger() == 5; }) - customersarray;
This updates the customer variable to be the new size of the array, but doesn't free or reallocate any memory. Since you are using dynamic arrays and pointers you are responsible for that.
Which is why you should really not be using pointers or arrays, but using vectors instead.
std::vector<Customer> customerVector;
Life will be so much simpler.
Type of "this" is a constant pointer which means you cant change where it points
Your function can return a boolean and if its true just set your pointer to null
You'll be much better off using a std::vector, all memory memory management gets much safer. You cannot modify the this pointer, but that would be meaningless anyway:
It is a local variable, so any other pointer outside would not be changed, not even the one you called the function on (x->f(): the value of x is copied into this).
It contains the address of the current object - the current object is at a specific memory location and cannot be moved away from (not to be mixed up with 'moving' in the context of move semantics!).
You can, however, delete the current object (but I don't say you should!!!):
class Customer
{
static std::vector<Customer*> customers;
public:
void commitSuicide()
{
auto i = customers.find(this);
if(i != customers.end())
customers.erase(i);
delete this;
}
}
Might look strange, but is legal. But it is dangerous as well. You need to be absolutely sure that you do not use the this pointer or any other poiner to the current object any more afterwards (accessing non-static members, calling non-static functions, etc), it would be undefined behaviour!
x->commitSuicide();
x->someFunction(); // invalid, undefined behaviour!!! (x is not alive any more)
Similar scenario:
class Customer
{
static std::vector<std::unique_ptr<Customer>> customers;
public:
void commitSuicide()
{
auto i = customers.find(this);
if(i != customers.end())
{
customers.erase(i); // even now, this is deleted!!! (smart pointer!)
this->someFunction(); // UNDEFINED BEHAVIOUR!
}
}
}
If handling it correctly, it works, sure. Your scenario might allow a much safer pattern, though:
class Customer
{
static std::vector<std::unique_ptr<Customer>> customers;
public:
Customer()
{
customers->push_back(this);
};
~Customer()
{
auto i = customers.find(this);
if(i != customers.end())
customers.erase(i);
}
}
There are numerous variations possible (some including smart pointers); which one is most appropriate depends on the use case, though...
First of all, attending to RAII idiom, you are trying to delete an object before using its destructor ~Customer(). You should try to improve the design of your Customer class through a smart use of constructor and destructor:
Customer() {// initialize resources}
~Customer() {// 'delete' resources previously created with 'new'}
void deactivate() {// other internal operations to be done before removing a customer}
Then, your constructor Customer() would initialize your internal class members and the destructor ~Customer() would release them if necessary, avoiding memory leaks.
The other question is, why do you not use another type of Standard Container as std::list<Customer>? It supports constant time removal of elements at any position:
std::list<Customer> customers
...
customers.remove_if([](Customer foo) { return foo.getAngerLevel() == 5; });
If you only expect to erase Customer instances once during the lifetime of the program the idea of using a std::vector<Customer> is also correct.
I am using c++03, and trying to figure out which container to use. The hardware is MSP430F5324 with total of 6k of RAM (only 5k is available to me), and 64k flash. I am trying to store combination of derived classes, for example:
class OptNode {
public:
virtual ~OptNode();
explicit OptNode(uint16_t option_no) : option(option_no), _next(0) {}
protected:
uint16_t option;
unsigned length;
};
// --- Use heap memory for the option
class OptNodeDynamic : public OptNode {
public:
// --- assignment operators and copy constructor are not defined
OptNodeDynamic(const OptNodeDynamic &cSource);
OptNodeDynamic& operator= (const OptNodeDynamic &cSource);
OptNodeDynamic(uint16_t option_no, uint8_t* option_data, size_t length);
~OptNodeDynamic();
private:
uint8_t* data;
};
// --- Use the c string for the option
class OptNodeCstr : public OptNode {
public:
OptNodeCstr(uint16_t option_no, const char* option_data);
private:
const char* data;
};
// ----- OptNodeDynamic() ------------------------------------------------------
OptNodeDynamic::OptNodeDynamic(uint16_t option_no,
uint8_t* option_data,
size_t length) : OptNode(option_no) {
//
option = option_no;
data = new uint8_t[length];
std::memcpy(data, option_data, length);
}
// ----- ~OptNodeDynamic() -----------------------------------------------------
OptNodeDynamic::~OptNodeDynamic() {
if (data != 0 && length != 0) {
delete data;
}
}
// ----- OptNodeCstr() ---------------------------------------------------------
OptNodeCstr::OptNodeCstr(uint16_t option_no,
const char* option_data)
: OptNode(option_no),
data(option_data) {
//
length = 0;
for (const char* itr_ptr = data; *itr_ptr != '\0'; ++itr_ptr, ++length) {
/* no code */
}
return;
}
The container should allocate only what it needs for each of the objects. I should be able to add objects of type B or C in any order and as many as needed. Is there such container? Or do I instantiate each object using new operator and pass the pointer to a container, such as list.
Edit: I added hardware description and changed class from example to the actual. I am thinking that the system will need from 0 to 8 instances during data upload process, which happens at most once per hour. Other times, I can use that heap memory for something else.
None.
You do not have enough memory on your platform for the C++ runtime library. You should not and cannot use any C++ container.
Frankly I'd stick with good ol' C for this. As for what code you actually write to achieve your goal, well that depends on your goal. :)
There is a significant overhead when allocating individual objects with new (up to several tenths of bytes per call to new).
If you want to save memory, the best thing to do is to pre-allocate three chunks of memory (pools) for storing the instances of A, B and C, and overload the new and delete operators for A,B and C.
You will find examples in the answer of the following question:
Using operator new and operator delete with a custom memory pool/allocator
Preallocating all the objects at init time and then trying to use the pointers throughout the life cycle of the process will be better idea.
I have a class which has a CArray object, I need to get values from this CArray to another class, but so far have failed to do so.
class CTempGridClass: public CTableCtrl {
public:
CArray<CArray<float,float>, CArray<float,float>&> *m_row2;
};
class CCorePassageAreasPage : public CDialog {
DECLARE_DYNCREATE(CCorePassageAreasPage)
public:
enum { IDD = IDD_CORE_PASSAGE_AREA };
CArray<CArray<float,float>, CArray<float,float>&> m_row;
CTempGridClass Grid;
};
BOOL CCorePassageAreasPage::OnSetActive() {
Grid.m_row2 = &m_row;
}
How can I access m_row2 values? I tried
float x = m_row2[0][1];
but this gives out an "'initializing' : cannot convert from 'CArray' to 'float'" error. I can do the above assignment to m_row without any errors.
I know that I can avoid this by using a vector instead, but the 'CCorePassageAreasPage' is created by someone else and I don't want to change it.
m_row2 is a pointer; so m_row2[nRow] would refer to element nRow of an array of CArray, if it pointed an array. Since it (presumably) only points to a single object, it just accesses invalid memory.
You almost certainly don't want it to be a pointer; since you say the class "has" it, it should just be a member with no unnecessary indirection.
If you do want a pointer for some reason, then you'll need to dereference it to access the array it points at:
float x = (*m_row2)[nRow][j];
I am looking to be pointed in the right direction.
I have 1 class Event
class Event{
private:
vector<string> Question;
char Mode;// 1 = Ascending 2 = Descending 3 = None
string EventName;
public:
Event(string Name){
EventName = Name;
SetQuestionSize();
SetQuestion();
Mode = 3;
}
void SetName(string NewName){
EventName = NewName;
}
void SetQuestionSize(){
Question.resize(15);
}
int ReturnQuestionSize(){
return Question.size();
}
void SetQuestion(){
Question[0]="Enter ";
Question[1]="1 ";
Question[2]="to ";
Question[3]="sort ";
Question[4]="in ";
Question[5]="ascending ";
Question[6]="order, ";
Question[7]="2 ";
Question[8]="for ";
Question[9]="Descending, ";
Question[10]="or ";
Question[11]="3 ";
Question[12]="to ";
Question[13]="ignore ";
Question[14]=EventName;
}
string ReturnQuestion(int Index){
return Question[Index];
}
/*vector<string> ReturnQuestion(){
return Question;
}*/
void SetMode(char NewMode){
if (NewMode == '0' || NewMode == '1' || NewMode == '2')
Mode = NewMode;
}
char ReturnMode(){
return Mode;
}
string ReturnName(){
return EventName;
}
};
This is will be a member of a second object, which will use Event's functions to store data in Event's members.
The problem I'm having is declaring an array of Event objects in my second object. When researching I came across ways to use an array of pointers to the first object, and some operator '->' that I'm guessing is related to virtual functions.
class WhatTheyWant{
Event *events[2];
public:
WhatTheyWant(){
events[0]= new Event("Miss");
events[1]= new Event("Dodge");
}
};
I'm very ignorant about pointers, and I know I will have to learn them eventually, but are they the best way to go or is there a better.
Since your Event class doesn't have a default constructor, you need to explicitly construct each object with its name, so the way you're doing it currently is the only way to do it.
If you add a default constructor to Event, you can do it in at least two other ways:
If you will always have a (small) fixed number of objects, you can just declare an array of constant size:
Event events[2];
Doing this will automatically construct the objects when WhatTheyWant is created, so you just need to set the names afterwards:
WhatTheyWant() {
events[0].SetName("Miss");
events[1].SetName("Dodge");
}
If you want to have a variable number of events, you can declare a single pointer and dynamically allocate an array of objects:
Event *events;
And you could probably give the number as a parameter to the constructor:
WhatTheyWant(int numEvents) {
events = new Event[numEvents];
for (int i = 0; i < numEvents; i++)
events[i]->SetName("...");
}
Also, not directly related to your question, but your Mode variable would be better modeled using an enumeration instead of a char. Using an enum makes it clearer as to what the variable really means, rather than using values like 0, 1 and 2. For example:
public:
enum ModeType { Ascending, Descending, None };
private:
ModeType Mode;
public:
Event() {
...
Mode = Ascending;
}
void SetMode(ModeType NewMode) {
Mode = NewMode;
}
ModeType ReturnMode() {
return Mode;
}
You can use either array of objects or array of pointers.
Array of objects go like below.
class WhatTheyWant{
Event events[2];
public:
WhatTheyWant()
{
events[0] = Event("Miss");
events[1] = Event("Dodge");
}
};
Note: You need to add default constructor to your event class to compile the above approach.
With the above approach, you do not need to take care of freeing Event objects. Whenever WhatTheyWant object gets destroyed, event objects get destroyed.
Array of pointers approach goes like you mentioned.
But you need to take care of freeing the memory allocated(Unless you use auto_ptr or some c++0x equivalent).
Deletion should happen in destructor like below.
class WhatTheyWant{
Event *events[2];
public:
WhatTheyWant(){
events[0]= new Event("Miss");
events[1]= new Event("Dodge");
}
~WhatTheyWant()
{
delete events[0];
delete events[1];
}
};
In C++, pointers are just like arrays
in your WhatTheyWant class, you define the private member:
Event *events[2];
This is an array of arrays (2D array) with variable length (of arrays) and 2 element in each array.
and the operator '->' is used when you want to access a (member of some kind of object) and that is called an object pointer (a pointer which points to an object) but when you define a normal object variable you use '.' operator.
If you've got the courage and knowledge to use them they are very useful but in general they're dangerous and that's why the new languages tend to go to the managed way.