Creating multiple objects and passing parameters through constructor - c++

I am trying to understand how to create multiple objects(20 in the current case) and pass parameter to the constructor as shown in the comments of the code. Unfortunately, I cannot pass parameters as well as have an array of objects at the same time.
I tried this as well to create the object convector con(100,200, construct(20)); but it didn't seem to give the desired result
#include <iostream>
class construct {
public:
int a, b;
// Default Constructor
construct(int x1,int x2)
{
a = x1;
b = x2;
}
int getX1(){
return a;
}
int getX2(){
return b;
}
};
int main(){
int p,q;
construct* con = new construct[20](100,200);
for (unsigned int i = 0; i < 20; i++) {
p=con[i]->getX1();
q=con[i]->getX2();
printf("%d %d \n",p,q);
}
delete con;
return 1;
}
Expected result would be 20 objects created.

Just use std::vector. Seriously, there's no reason not to.
std::vector<construct> con(20, {100, 200});

Yeah, for this you are likely to need placement new sadly (or use std::vector, and pass a newly constructed object as the second argument).
// call global new (effectively malloc, and will leave objects uninitialised)
construct* con = (construct*)::operator new (sizeof(construct) * 20);
// now call the ctor on each element using placement new
for(int i = 0; i < 20; ++i)
new (con + i) construct(100, 200);

Related

Why i Get Access Violation When i tried to access Lambda Local Variable Via Address [duplicate]

I need to create several objects and put them in a list (for which I am using std::vector). Also, I need the list items to point to the addresses of the objects so that the changes I make to the objects are reflected in the list too.
But the thing is, every item in the list is pointing to the last object created in the loop.
for(int i=0;i<50;i++){
for(int j=0;j<50;j++){
Grass g1;
g1.position.x = i;
g1.position.y = j;
grassList.push_back(&g1);
}
}
The the attributes of grass objects in the list should be..
[0,0]
[0,1]
[0,2]
.
.
.
.
[49,49]
But it's coming out to be..
[49,49]
[49,49]
[49,49]
[49,49]
.
.
.
[49,49]
(Modern-C++ update at the end)
If you're accustomed to other languages that use ref-counting of variables, you might have expected that
Grass g1;
was creating a new "Grass" object every iteration of the loop. It's not, C++ isn't a ref-counted language.
Instead, it creates a scoped local variable on the stack.
Because you're doing this in a loop, it's probably going to be at the same location in memory every time.
You will either need to:
Instead of pointers, just make your container a container of Grass objects: let the container handle allocation for you.
Use C++11's unique_ptr and C++14's make_unique to create an instance of Grass dynamically for each iteration of the loop. When the vector containing the unique_ptrs goes out of scope, they will be automatically freed.
Use the new and delete keywords to manually allocate and release Grass objects to point to.
Option 1:
#include <vector>
struct Grass {
struct {
int x, y;
} position;
};
int main() {
std::vector<Grass> grassList;
for(int i=0;i<50;i++){
for(int j=0;j<50;j++){
Grass g1;
g1.position.x = i;
g1.position.y = j;
grassList.push_back(g1);
}
}
}
Live demo: http://ideone.com/DQs3VA
Option 2:
#include <memory>
#include <vector>
struct Grass {
struct {
int x, y;
} position;
};
int main() {
std::vector<std::unique_ptr<Grass>> grassList;
for(int i=0;i<50;i++){
for(int j=0;j<50;j++){
auto g1 = std::make_unique<Grass>();
g1->position.x = i;
g1->position.y = j;
grassList.push_back(std::move(g1));
}
}
}
Live demo: http://ideone.com/hJUdwR
Option 3:
#include <vector>
struct Grass {
struct {
int x, y;
} position;
};
int main() {
std::vector<Grass*> grassList;
for(int i=0;i<50;i++){
for(int j=0;j<50;j++){
Grass* g1 = new Grass;
g1->position.x = i;
g1->position.y = j;
grassList.push_back(g1);
}
}
// ...
for (auto& g1: grassList) {
delete g1;
}
grassList.clear();
}
Live demo: http://ideone.com/GTk7ON
C++11 introduced emplace_back which lets you allocate and construct the entry in the container in one go.
#include <vector>
struct Grass {
struct {
int x, y;
} position;
// because x and y are inside a private sub-struct,
// we'll need a constructor to pass the values in.
Grass(int x, int y) : position{x, y} {}
};
int main() {
std::vector<Grass> grassList{}; // default initialized.
static constexpr size_t dim = 10; // name the constant (DIMension)
grassList.reserve(dim); // allocate memory in advance
for (auto i = 0; i < dim; i++) {
for(auto j = 0; j < dim; j++) {
grassList.emplace_back(i, j);
}
}
// no cleanup required
}
live demo: https://gcc.godbolt.org/z/G1YsW7hMs
You're pushing pointers to local variables to the vector. Local variables get destroyed at the end of their scope (the second-to-last } in this case). Therefore, dereferencing any of those pointers after the } is undefined behavior. The output you're seeing is a completely valid result of undefined behavior.
Using pointers here just doesn't make sense. Use them (including new) only when absolutely necessary. For more info, see Why should I use a pointer rather than the object itself?
This is the right way:
std::vector<Grass> grassList;
// ^^^^^ not pointers!
for(int i=0; i<50; ++i) {
for(int j=0; j<50; ++j) {
Grass g1;
g1.position.x = i;
g1.position.y = j;
grassList.push_back(g1);
}
}
If for whatever (unspecified) reason you need to store the pointers to the locations of the objects, you need this
std::vector<Grass*> grassList; // Assumed you already have something like this
for(int i=0;i<50;i++){
for(int j=0;j<50;j++){
Grass* gp1 = new Grass;
gp1->position.x = i;
gp1->position.y = j;
grassList.push_back(gp1);
}
}
This avoids the destruction of the objects pointed at by the pointers you are storing. See, e.g., Creating an object: with or without `new`
You will have to take care of suitably deleting objects with delete to free memory.
But depending on your needs, you may also use an array of objects instead of an array of pointers, as suggested by tuple_cat.

How to modify array inside function which doesn't take this array as parameter

What I need is to modify pTab array inside modifyAA(int a) function.
How can I achieve this?
Example Code:
int modifyAA(int a);
int main()
{
*pTab=new int[10]; int a=13;
for(int i=0;i<=9;i++)
pTab[i]=88;
modifyAA(a);
//I'd like to have pTab to be modified after function invoke
return 0;
}
modifyAA(int a){
for(int i=0;i<=9;i++)
pTab[i]=pTab[i]+1;
a=a+pTab[0];
return a;
};
Is it possible to modify array when function doesn't take it as parameter ?
You can use a global variable for the pointer to the first element of the dynamic array:
int * pTab;
int printAA(int a)
{
for (unsigned int i = 0 i != 10; ++i)
{
++pTab[i];
}
return a + pTab[0];
}
int main()
{
pTab = new int[10];
// populate
printAA(13);
}
You could use global variables. This could be practical especially if several functions like printAA() would need to call it.
However there is a risk of using *pTab before it's allocated. And also, you remember now the size, but if later you'd change the size to 10, you would have to find back all the places where you've hardcoded the 10 or the 9.
If the goal of not passing the parameter is mainly because you call the function a lot of times you could opt for a std::bind, creating a kind of dynamic function:
#include <iostream>
#include <functional>
int printDynArr(int* dynarr, size_t sz, int a) // proper function with all parameters
{
for (size_t i = 0; i < sz; i++)
dynarr[i]++; // It's a pointer, so you modify the data where it is stored
a += dynarr[0];
return a;
};
int main()
{
int *pTab = new int[10]; int a = 13; //declaring and alocating - dynamic array
auto printAA = std::bind<int>(printDynArr, pTab, 10, std::placeholders::_1); // dynamic function shortcut with predefind parameters
...
printAA(a); //using function without giving pTab as argument.
std::cin.get();
return 0;
}
If you were to do this "The C++ way", you could use a vector and iterators from stdlib, like so:
#include <vector>
typedef std::vector<int> PTab; // Defines a type for your pTab, it's a vector of integers
int printAA(PTab::iterator from, PTab::iterator until, int a); //declaring some func
int main()
{
PTab pTab(10, 88); // Initializes pTab vector to 10 elements all containing 88
int a = 0;
printAA(pTab.begin(), pTab.begin() + 10, a);
return 0;
}
int printAA(PTab::iterator from, PTab::iterator until, int a)
{
for (PTab::iterator i = from; i != until; ++i)
{
*i++; // Increments current element by 1
}
a += *from; // Adds the value of the from element to a
return a;
};
This way you don't pass the vector itself to the function, instead, you only pass a range of iterators, which gives the function a possibility to access the contents of the vector, but not to modify the vector object itself (ie. clear it, resize it, etc.).

Passing Class with a Pointer Member

I have a simple matrix class which has a 2d integer pointer field in it. When I call following function multiple times, it gives me a glibc error on Linux machine. When I have "otherM.value = '\0';" add this line to the end of function, problem resolves. Could somebody explain me why I have this dangling pointer issue, although class is passed by copy, not by reference? Pointer members are passed by reference?
void matrix::sub(matrix otherM)
{
if(dimX!=otherM.dimX || dimY!=otherM.dimY)
return;
int** rowPtr = value;
int** otherMrowPtr = otherM.value;
for(int i=0;i<dimX;i++){
for(int j=0;j<dimY;j++){
(**rowPtr) = (**rowPtr) - (**otherMrowPtr);
(*rowPtr)++;
(*otherMrowPtr)++;
}
(*rowPtr)-=dimY;
(*otherMrowPtr)-=dimY;
rowPtr++;
otherMrowPtr++;
}
rowPtr = '\0';
otherMrowPtr = '\0';
otherM.value = '\0';
}
matrix::matrix(int x, int y){
dimX = x;
dimY = y;
// allocate here
value = new int*[dimX];
int** rowPtr = value;
for(int i=0;i<dimX;i++){
*rowPtr = new int[dimY];
rowPtr++;
}
}
matrix::~matrix(){
if(value!=NULL){
int** rowPtr = value;
for(int i=0;i<dimX;i++){
delete[] (*rowPtr);
rowPtr++;
}
rowPtr-=dimX;
delete[] rowPtr;
rowPtr = '\0';
}
value = '\0';
}
Did you implement copy constructor, assignment operator and destructor for your class? If not then go and implement those since you're managing a resource.

Dynamically allocating array of objects

I need a double pointer of type DizzyCreature (my class) to point to an array of DizzyCreature pointers. When I run it I get "Access violation reading location 0x...". I can make a DizzyCreature* and call its member functions just fine, but when cannot run through the array and do the same thing for each obj.
I am following these instructions:
http://www.cplusplus.com/forum/beginner/10377/
Code
Server.h:
class Server
{
public:
Server(int x, int y, int count);
~Server(void);
void tick();
private:
DizzyCreature** dcArrPtr;
DizzyCreature* dcPtr;
int _count;
};
Server.cpp:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count]; // this works just fine
dcArrPtr = new DizzyCreature*[count]; // this doesn't (but gets past this line)
_count = count;
}
Server::~Server(void)
{
delete[] *dcArrPtr;
delete[] dcPtr;
}
void Server::tick()
{
dcPtr->takeTurn(); // just fine
for (int i = 0; i < _count; i++) {
dcArrPtr[i]->takeTurn(); // crash and burn
}
}
EDIT:
The member function takeTurn() is in a parent class of DizzyCreature. The program makes it into the function, but as soon as it attempts to change a private member variable the exception is thrown. If it matters, DizzyCreature is of type GameCreature and WhirlyB as this is an assignment on MI.
You have allocated space for dcArrPtr, but didn't allocate every object in this array. You must do following:
Server::Server(int x, int y, int count)
{
dcPtr = new DizzyCreature[count];
dcArrPtr = new DizzyCreature*[count];
for ( int i = 0; i < count; i++ ) {
dcArrPtr[ i ] = new DizzyCreature;
}
_count = count;
}
Server::~Server(void)
{
for ( int i = 0; i < count; i++ ) {
delete dcArrPtr[ i ];
}
delete[] *dcArrPtr;
delete[] dcPtr;
}
This:
dcPtr = new DizzyCreature[count];
"creates" an array of DizzyCreatures, whereas:
dcArrPtr = new DizzyCreature*[count];
"creates" an array of pointers to DizzyCreatures, but crucially doesn't create instances for those pointers to point to.
The preferred solution is to use a standard container for tasks like this anyway though. If you really want to do it like this (and are aware that it's not best practice to do this manually) then you'll need a loop to call new for eachelement in the array of pointers.
You allocate an array of count pointers instead of an array of count objects.
Instead of
dcArrPtr = new DizzyCreature*[count];
you might want to
dcArrPtr = new DizzyCreature[count];
You're allocating an array of pointers, but those pointers aren't valid until you set them to something.
double **arr = new double*[10];
for(int i=0;i<10;++i) {
arr[i] = new double[10];
}
That said, when starting out with C++ you should probably avoid raw arrays and instead use std::array and std::vector:
class Server
{
public:
Server(int x, int y, int count);
void tick();
private:
std::vector<std::vector<DizzyCreature>> dcArrPtr;
std::vector<DizzyCreature> dcPtr;
};
Server::Server(int x, int y, int count)
{
dcPtr.resize(count);
dcArrPtr.resize(count);
}
void Server::tick()
{
dcPtr[0].takeTurn();
for (int i = 0; i < dcArrPtr.size(); i++) {
dcArrPtr[i][0].takeTurn();
}
}
Use a
std::vector<std::vector<DizzyCreature>>
Furthermore, if you want to use raw pointers (which I do not recommend), you'll have to allocate memory for each pointer in your array.
class A
{
std::vector<std::vector<int>> v_;
public:
A()
: v_(500, std::vector<int>(500))
{} // 500 x 500
};
class B
{
int** v_;
public:
B()
: v_(new int*[500])
{ // not even exception safe
for (int i = 500; i--; )
v_[i] = new int[500];
}
~B()
{
for (int i = 500; i--; )
delete[] v_[i];
delete[] v_;
}
};
If you would have seen the implementation of dynamic memory allocation of 2-Dimensional array . That would have given you a better insight of how to proceed in such cases . Most of the answers has already answered you what to do . But just go through any link and see how is memory allocated in case of 2-D array . That Will also help you .

initializing a vector of custom class in c++

Hey basically Im trying to store a "solution" and create a vector of these. The problem I'm having is with initialization. Heres my class for reference
class Solution
{
private:
// boost::thread m_Thread;
int itt_found;
int dim;
pfn_fitness f;
double value;
std::vector<double> x;
public:
Solution(size_t size, int funcNo) : itt_found(0), x(size, 0.0), value(0.0), dim(30), f(Eval_Functions[funcNo])
{
for (int i = 1; i < (int) size; i++) {
x[i] = ((double)rand()/((double)RAND_MAX))*maxs[funcNo];
}
}
Solution() : itt_found(0), x(31, 0.0), value(0.0), dim(30), f(Eval_Functions[1])
{
for (int i = 1; i < 31; i++) {
x[i] = ((double)rand()/((double)RAND_MAX))*maxs[1];
}
}
Solution operator= (Solution S)
{
x = S.GetX();
itt_found = S.GetIttFound();
dim = S.GetDim();
f = S.GetFunc();
value = S.GetValue();
return *this;
}
void start()
{
value = f (dim, x);
}
/* plus additional getter/setter methods*/
}
Solution S(30, 1) or Solution(2, 5) work and initalizes everything, but I need X of these solution objects. std::vector<Solution> Parents(X) will create X solutions with the default constructor and i want to construct using the (int, int) constructor. Is there any easy(one liner?) way to do this? Or would i have to do something like:
size_t numparents = 10;
vector<Solution> Parents;
Parents.reserve(numparents);
for (int i = 0; i<(int)numparents; i++) {
Solution S(31, 0);
Parents.push_back(S);
}
the example I gave as a comment uses copy constructor to create new objects.
You can do the following:
// override copy constructor
Solution(const Solution &solution) {
... copy from another solution
}
however be careful, as you no longer going to have exact object copy/construct if you introduce random generation in your copy constructor, i.e. Solution y = x; y != x
your best solution is something like you already have in my opinion
I have used the Boost assignment library for tasks like this. You may find it useful....