Problem with passing list pointer to a function - c++

In my program I have a list which is a pointer list<COffenceUnit*>* m_attack = nullptr; I initialize this list like that: m_attack = new list<COffenceUnit*>(); in the constructor. At some point in the code I want to send this list to another constructor as a reference. This is the constructor that receives the list:
GameMap::GameMap(const std::list<CDefenceUnit*>* &defenseUnits, const std::list<COffenceUnit*>* &offenseUnits)
{
mGameMap = new int* [GRID_SIZE];
for (int i = 0; i < GRID_SIZE; ++i)
mGameMap[i] = new int[GRID_SIZE];
updateMap(defenseUnits, offenseUnits);
}
However the compiler throws an error that says:
Error C2664 'GameMap::GameMap(const GameMap &)': cannot convert argument 1 from
'std::list<CDefenceUnit *,std::allocator<_Ty>> **' to 'const std::list<CDefenceUnit *,std::allocator<_Ty>> *&'
I can't figure out what am I doing wrong here.

You're trying to call the function with a pointer-to-pointer-to-list (std::list<...>**), but the function expects a pointer-to-list (std::list<...>*), so the conversion fails.
Dereference the argument to remove one level of pointer. For example if you had GameMap(defenseUnits), then change that to GameMap(*defenseUnits).
Also you should almost never new std containers, so to initialize your m_attack, it's recommended to do it without new (i.e. without dynamic allocation), like so:
list<COffenceUnit*> m_attack;
Then you also don't need to do m_attack = list<COffenceUnit*>(); later, because the list is already default initialized by the list's constructor.
This also helps you avoid multiple levels of pointers, such as in std::list<...>**.
Also you probably want std::vector instead of std::list, the latter is rarely a better choice.

Related

C++ vector initialise a vector of agents for a genetic algorithm

I have the following C++ code, but I get some errors in mainly stuff like the following (after the block of code) the Agent is just a class that I created in a seperate file
vector<Agent> population;
for (vector<int>::iterator i = population.begin(); i != population.end(); ++i) {
population.push_back(new Agent(generateDna(targetString.size())));
}
I get the following errors
no suitable user-defined conversion from "__gnu_cxx::__normal_iterator>>" to "__gnu_cxx::__normal_iterator>>" exists
2.no operator "!=" matches these operands -- operand types are: __gnu_cxx::__normal_iterator>> != __gnu_cxx::__normal_iterator>>
3.no instance of overloaded function "std::vector<_Tp, _Alloc>::push_back [with _Tp=Agent, _Alloc=std::allocator]" matches the argument list -- argument types are: (Agent *) -- object type is: std::vector>
and I'm new to c++ so these things might be self explanatory, but I don't know what they mean.
The main problem is that you are iterating over collection in which you append during the cycle and even through iterator which is defined as int instead of Agent. Create new vector and push your generated values into this new vector.
Also be aware of using new keyword. You must dealocate that memory later.
Solution:
vector<Agent> population;
vector<Agent> newPopulation;
for (vector<Agent>::iterator i = population.begin(); i != population.end(); ++i) {
newPopulation.push_back(Agent(generateDna(targetString.size())));
}
Your current compilation issue is that you're trying to store a std::vector<Agent>::iterator into a std::vector<int>::iterator. These are two completely different types.
Then there's your runtime issue (after you actually add elements to your container because right now you have none), your iterators might be invalidated after a push_back and you'll have UB because you're modifying the container while you're looping over it.
Then there's the issue where you're trying to store an Agent* into a vector of Agent's.
All in all:
std::vector<Agent> population;
//fill your vector.. otherwise loop is useless because size is 0..
auto size = population.size();
for (unsigned int i = 0; i < size; ++i) {
population.push_back(Agent(generateDna(targetString.size())));
}

return a std::vector in c++

EDIT
*Please , upvote this topic because I cant ask anymore question in this forum.
Programming is my life and I'm just stuck because of an automated banning . Thank you ( or I need the help of a moderator to solve this problem *
I'm a beginner programmer in c++ and I want to basically return a std::vector
When I debug my code I get function call missing argument list . Here is my simple code
Thanks for your help
#include "stdafx.h"
#include <vector>
#include <iostream>
static std::vector<int> returnStaticVector();
static std::vector<int> returnStaticVector(){
std::vector<int> vectorInt = std::vector<int>();
vectorInt.push_back(0);
return vectorInt;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<int> a = std::vector<int>();
a = returnStaticVector(); // Compile , but error when I try to access to the size of the std::vector
//int size = a.size; //error C3867: 'std::vector<int,std::allocator<_Ty>>::size': function call missing argument list; use '&std::vector<int,std::allocator<_Ty>>::size' to create a pointer to member
//int size = &a.size; // & Illegal operation
//int& size = a.size; //error C3867: 'std::vector<int,std::allocator<_Ty>>::size': function call missing argument list; use '&std::vector<int,std::allocator<_Ty>>::size' to create a pointer to member
int* size = a.size; //error C3867: 'std::vector<int,std::allocator<_Ty>>::size': function call missing argument list; use '&std::vector<int,std::allocator<_Ty>>::size' to create a pointer to member
return 0;
}
In std::vector size is a member function, not a member variable. You use it like this:
int size = a.size();
If you don't have the parentheses, it is a syntax error.
Incidentally, another thing you can do to simplify your code is declare vectors like this:
std::vector<int> a;
Or in C++11
std::vector<int> a{};
Both of these will default-construct the vector -- this works for any class type.
Doing it this way,
std::vector<int> a = std::vector<int>();
is not as good because it is longer and makes you type things twice, and also it copy initializes it rather than default constructing it, which is slightly different and may be less efficient.
First things first -- The real compile problem in your code is because you have used a.size instead of a.size(). Try changing that and the code should compile successfully.
Apart from that, I don't think it's a good idea to return a vector like what you have done. Try passing vectors using reference from the calling function. That is much better design.
If you are still thinking about return by value think in terms of Copy elision which is an optimization implemented by compilers to prevent unnecessary copies in many cases. It makes returning by value or pass-by-value feasible in many cases.
Read more about copy elisions here :-
http://en.cppreference.com/w/cpp/language/copy_elision
What are copy elision and return value optimization?

pushing back a class object into a vector

I have a vector that takes in a class object but when I try to push back the object I have created into the vector I am getting these problems and don't know how to getnaround it. Can anyone help me please ?
void populate( std::vector<NV*> vNav, NV *nVess);
creating the object class
NV vPB;
object class variables matching up
vPB.name = namE;
vPB.type = typE;
vPB.length = lengtH;
vPB.speed = speeD;
vPB.range = rangE;
vPB.serialNum = serialNuM;
vPB.serialNum = beaM;
vPB.displacement = displacemenT;
vPB.draft = drafT;
vPB.isActive = isActivE;
namE = name;
typE = type;
lengtH = length;
speeD = speed;
rangE = range;
serialNuM = serialNum;
beaM = beam;
displacemenT = displacement;
drafT = draft;
isActivE = isActive;
vNav.push_back(vPB);
keep getting error error C2664: cannot convert parameter 1 from 'N_V::NV' to 'N_V::NV *&&'
and also keep getting error IntelliSence no instance of overload function
The vector is expecting a pointer to an object whereas the vPB you are pushing back is not a pointer to an object but rather the object itself.
The minimum you can do to fix this is:
NV* vPB = new NV();
vPB->name = namE;
... and similarly for all the members you need to initialize ...
vNav.push_back(vPB);
Secondly the vNav vector is only going to exist within the context of that function because it is being passed by value. You probably want to take the argument by reference. This means changing your function's signature to:
void populate( std::vector<NV*>& vNav, NV *nVess);
Lastly it's not advisable to use naked pointers if you can help it. Try looking into shared_ptr and unique_ptr as a more advanced step to ensure that the object's lifetime is correctly managed and you don't leak memory allocations.
vNav is declared as std::vector<NV*>, but you try to push a NV type into there, an object not a pointer. So it's a type mismatch. You also pass the vector by value, which is probably not intended.
Using vector of pointers will be quite problematic. Because you need to manually allocate space for objects and then remember to allocate them. I would advise to revise the code to use std::vector<NV> or at least read about smart pointers.
As others pointed out, you are trying to insert an object where the type should be object pointer. Another error is you are passing the vector by value, it should be by reference, otherwise the caller will not see the effect of insertion.
void populate( std::vector<NV*>& vNav, NV *nVess);
I would write your populate function as
void populate( std::vector<NV>& vNav, NV& nVess);
unless you want to add pointers to the objects inside the vector.
And it is not clear where you get this error. Can you post the code where you get the error? Is it in push_back? If yes, then it's because you are trying to push back an object but your vector expects a pointer to object.

array of objects where constructor has an argument

I want to have an array of objects.
Each object has a constructor with one argument.
My object array initialisation :
set s[]=new set[n]; // creates an array of n objects of class set
However, it says that I cannot do so, because my constructor requires an argument.
My Constructor:
set(int size){}
I've understood the problem, but cant think of a good solution.
What I can do, is either initialise each object seperately :
set s1(size);
set s2(size); //& so on.....
or remove the argument from constructor......both solutions are not quite satisfactory
Can anyone help me out to find a better solution to this ?
Note: 'size' value of each object is different/dynamic
#include <vector>
...
std::vector<set> s(n, set(x,y,z));
This will create a vector (a dynamically resizeable array) of n set objects, each a copy of set(x,y,z). If you want to use different constructors for various elements, or the same constructor with different arguments:
std::vector<set> s; // create empty vector
s.push_back(set(x,y,z));
s.push_back(set(y,z,x));
...
... // repeat until s.size() == n
You can make a different constructor that takes no arguments and initializes the values, and then set the values of each variable in a loop
set() {
this.size = 0;
}
and then in a for loop initialize each element with the desired size, using direct binding or a getter/setter functions.
for(int i = 0; i < n; i++) {
s[i].size = value[i]; // or create a setter function
}

Using a constructor for an array of structures

I want to create an array of structures. The structure uses a constructor as shown below:
struct struct_seedinfo {
struct_seedinfo(const mxArray *prhs[ ],const int seed_id){
mxArray *mat_coords, *mat_defvectorinit, *mat_corrcoef, *mat_roi_id;
mat_coords = mxGetField(prhs[1],seed_id,"coords");
coords = mxGetPr(mat_coords);
mat_defvectorinit = mxGetField(prhs[1],seed_id,"defvectorinit");
defvectorinit = mxGetPr(mat_defvectorinit);
mat_corrcoef = mxGetField(prhs[1],seed_id,"corrcoef");
corrcoef = *(mxGetPr(mat_corrcoef));
mat_roi_id = mxGetField(prhs[1],seed_id,"roi_id");
roi_id = *(mxGetPr(mat_roi_id));
}
double *coords;
double *defvectorinit;
double corrcoef;
double roi_id;
static int num_seeds;
};
How could I create an arbitrary sized array of this structure? I need to allocate memory for it, but it seems like I would need to allocate memory without calling the constructor, and then call the constructor later in a forloop. Is there a good or preferred way of doing this? Thanks.
You can do std::vector<struct_seedinfo>. This will create an array and it will automagically increase in size when needed.
You'll also need to overload the copy constructor and copy-assignment operator for your struct to be able to be used in a vector. You need a destructor too. This is called the Rule of Three in C++
Well since the size stay constant, you can use the following solution :
*This assumes your ok with defining a default constructor.
First declare a default constructor in your class.
struct_seedinfo(){
//If you want to initlaize something.
}
Than you can use the following to create you array :
struct_seedinfo * arr = new struct_seedinfo[size_of_array];
And then you need for each space to do your specific build :
arr[i] = struct_seedinfo(//arguments);
This is if you badly need an array, i do also think the vector solution is better.