Reputation: 231
I am having an issue with creating a vector of structs. In my function AddApp I am unable to "push_back" the newly allocated struct into the vector. I get the error message "Invalid Arguments". I looked around to see if someone had a similar issue but nothing that helped. Can anyone point out whats the flaw in my logic? Thx.
class AppHolder
{
private:
struct Info
{
int refNumber;
string name;
string link;
};
vector<Info> dataBase;
public:
void AddApp(int ,string ,string );
};
void AppHolder::AddApp(int R, string N, string L)
{
Info *newApp = new Info;
newApp -> name = N;
newApp -> link = L;
newApp -> refNumber = R;
dataBase.push_back(newApp);
}
Upvotes: 3
Views: 33562
Reputation: 15824
The reason your code fails is that std::vector<Info>::push_back
requires that you pass it object of type Info
, but you pass Info*
.
We can solve this by using Info
objects directly instead of using pointers to new
ed variables:
void AppHolder::AddApp(int R, string N, string L)
{
Info newApp;
newApp.name = N;
newApp.link = L;
newApp.refNumber = R;
dataBase.push_back(newApp);
}
Info* newApp = new Info;
declares a pointer to Info, and initializing it with address of dynamically created object of type Info
, which must be deleted later, or destructor won't be called and memory won't be released.
Info newApp;
declares an automatic variable of type Info
which destructor is called at the end of scope, and its memory will be released.
Using new
with pointers is discouraged in modern C++, as it requires manual delete
of pointers, it's exception-unsafe (if exception is thrown before delete, resources aren't deleted) and involves writing a lot of code (copy constructor, copy assignment operator, destructor, move constructor, move assignment operator) to ensure your class works correctly. There are, however, situations where pointer usage is required (storing instances of derived classes in containers), in that case you want to use smart pointers which can manage resources for you.
Upvotes: 8
Reputation: 2962
The reason your compiler is complaining is that you defined dataBase to be a vector of Info
instances, and you are trying to push a pointer to an Info
instance.
Changing the vector<Info>
declaration to vector<Info*>
is one way, or change the AddApp
method:
void AppHolder::AddApp(int R, string N, string L)
{
Info newApp;
newApp.name = N;
newApp.link = L;
newApp.refNumber = R;
dataBase.push_back(newApp);
}
As others have pointed out, the use of new
in C++ is discouraged, so keeping your container definition is preferred. Change your implementation to use the correct type.
A commenter clarifies why one should be careful when using new
in C++.
Upvotes: 2
Reputation: 4515
The declaration
vector<Info> dataBase;
Declares a vector that takes Info
objects. In the initialiser,
Info *newApp = new Info;
newApp -> name = N;
newApp -> link = L;
newApp -> refNumber = R;
dataBase.push_back(newApp);
The statement dataBase.push_back(newApp);
tries to push a pointer to an Info
structure on to the vector (but your vector wants objects, not pointers to objects).
So, you either need to decalre a vector of pointers to Info
structures - vector<Info *>
- and remember to free each pointer in the class destructor. Or, just create an Info
structure on the stack (i.e. an actual object) and push that onto the vector (which will create a copy of the struct inside the vector - will use default struct copy constructor in your case, which is fine because the struct doesn't contain pointers etc or anything that requires or does not support a deep copy).
The latter method is safer, because you don't have to remember to free anything, and also more efficient in this case, probably, because although you're copying a structure, you don't make an expensive system call to the OS to make the memory allocation.
Upvotes: 2
Reputation: 2017
You must turn this:
vector<Info> dataBase;
into this:
vector<Info*> dataBase;
as you want to push_back a pointer, and vector is declared to take objects.
Upvotes: 0