C++ public constructor address - c++

After writing the code below:
#include <iostream>
using namespace std;
typedef struct Node {
int value;
Node(int index) {
value = index;
}
} Node;
int main() {
Node* arr[10];
for(int i = 0; i < 10; i++) {
arr[i] = &Node(i);
}
for(int i = 0; i < 10; i++)
cout << arr[i]->value << endl;
}
I saw that the code prints only 9's instead of all the numbers from 0 to 9 it was supposed to.
After debugging the code i saw that address of arr[i] for each i are the same, and Node(i) have freed the space for arr[i] only once, and after that the only thing it is value = index without freeing any other space. Why?

This line: arr[i] = &Node(i); is storing a pointer to a temporary object. Node(i) creates a temporary object that can be destructed at the end of the statement, at which point all references to it become invalid meaning the results of any code that dereferences arr[i] will be undefined. The reason in this case you get all 9's is because the compiler is optimizing the code -- since only 1 temporary Node(i) is being created at a time, the compiler is just reusing that memory each time through the loop.
To fix the problem, allocate memory off the heap for each object: arr[i] = new Node(i);. Then when you are done using them you will also need to remember to delete each one:
for (int i=0; i < 10; ++i) {
delete arr[i];
}
If you want to investigate farther, try adding some code to your Node class to see what's happening: for example print out the address of this in your constructor, and/or create a destructor that just prints a message out so you can see it being called.

To create new objects, use new Node(i) otherwise you are creating temporary objects on the stack which is why they are all the same.
Remember to call delete on each object that you get back from new.

&Node(i)
This expression creates a temporary variable and returns its address. The temporary is then destroyed, and the next time the expression is evaluated, another temporary is created in the same place — hence the identical addresses.
You should probably eliminate the use of pointers, and introduce a default value for Node.
#include <iostream>
using namespace std;
typedef struct Node {
int value;
Node(int index) {
value = index;
}
Node() : value( 0 ) {} // allow default construction
} Node;
int main() {
Node arr[10]; // default-construct array values
for(int i = 0; i < 10; i++) {
arr[i] = Node(i);
}
for(int i = 0; i < 10; i++)
cout << arr[i].value << endl;
}
Do not use new Node for each object individually. Always use a container object to manage a group of objects with similar semantics. You might use std::vector here, or std::array if you have it. The overhead introduced by std::vector will be less than that introduced by new.

Related

How to correctly initialise pointers within class function?

I am using a array of pointer's declared within a class to point to another array. When a pointer array element is initialised to a value within main that value is also carried to the array element it is pointing to. The following code show this and it works fine. However if I initialise the pointer within the init class function I get a segfault. Also if I try to access an element from the pointer array not initialised in main I also get a segfault.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
class testclass {
public:
double *Wgt;
double* *LWgt;
void init() {
Wgt = new double[26];
LWgt = new double*[26];
//segfault from here
*LWgt[5] = 22.34543;
}
};
int main() {
testclass *node;
node = new testclass[10];
for (int i = 0; i < 10; i++) {
node[i].init();
}
for (int i = 0; i < 5; i++) { //init_nconn here
node[i].LWgt[23] = &node[i + 5].Wgt[12];
}
node[6].Wgt[12] = 50.6987;
node[8].Wgt[12] = 0.999923;
cout << *node[1].LWgt[23] << *node[3].LWgt[23] << "--\n";
//No segfault
*node[1].LWgt[23] = 33.234;
cout << node[6].Wgt[12] << "---\n";
//No segfault here
cout << *node[1].LWgt[23] << "---\n";
//Segfault from here
cout << *node[3].LWgt[5] << "---\n";
}
Is there a way to initialise the pointer array within a class function without leading to a segfault?
LWgt = new double*[26];
allocates memory for 26 double* but does not allocate memory for the pointers themselves.
The line
*LWgt[5] = 22.34543;
causes undefined behavior since memory hasn't been allocated for any of the elements of LWgt.
In order to be able to use that, you have to allocate memory for LWgt[5] first.
LWgt[5] = new double[<SOME_SIZE>]; // Allocate an array
or
LWgt[5] = new double; // Allocate just one element.
That's because none of the pointers stored inside LWgt actually point to anything valid yet. Remember that a pointer will be initialized by the runtime with some random value that may or may not be a valid address. When you try to stuff a value inside an invalid address you're going to get an error.
You need to initialize the pointers inside LWgt to point to some actual double memory locations before you can assign any values to them:
void init() {
Wgt = new double[26];
LWgt = new double*[26];
for(int i = 0; i < 26; i++)
LWgt[i] = new double;
//segfault from here
*LWgt[5] = 22.34543;
}
As a side note, this kind of initialization is probably best done inside a constructor for your class rather than a special initialization function. The point of constructors is that they always run automatically when the class is instantiated. You don't have to worry about remembering to call an init function right after you create the object.
Lwgt is an array of pointers to double. You'd have to allocate each element in the array or remove the ** in the declaration.

c++ assign a 2D array to an Object

My code pass the compiler, but I have a question about the concept of the pointer.
main.cpp:
int main(int argc, const char * argv[])
{
int inputPuzzle[3][3];
std::cout << "Set the puzzle: " << "\n";
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
std::cin >> inputPuzzle[i][j];
}
}
puzzle puzzle_1 = *new puzzle(inputPuzzle);
puzzle_1.display();
return 0;
}
puzzle.h:
class puzzle
{
public:
puzzle();
puzzle(int [][maxCol]);
~puzzle();
public:
int puzz [maxRow][maxCol];
};
puzzle.cpp:
puzzle::puzzle(int a[][maxCol])
{
for (int i = 0; i < maxRow; i++) {
for (int j = 0; j < maxCol; j++) {
puzz[i][j] = a[i][j];
}
}
}
My question is about the statement :puzzle puzzle_1 = *new puzzle(inputPuzzle);
Why do I have to add "*" in front of the new object in which I want to assign a 2D array ?
You're programming C++, where new returns a pointer. When you use the asterisk it's the dereference operator, and basically turns a pointer into a non-pointer.
Using the dereference operator like that means that you actually lose the pointer created by new, and you can not free that allocated memory with delete which, of course, leads to a memory-leak.
To avoid losing the pointer, you have to declare the variable as a pointer:
puzzle* puzzle_1 = new puzzle(inputPuzzle);
Then you have to use the pointer member selector operator instead when accessing members:
puzzle_1->display();
And, to avoid leaking memory, when you're done with the pointer you must delete it:
delete puzzle_1;
However, in C++ there is seldom any need to use pointers; instead just declare it as a normal variable:
puzzle puzzle_1(inputPuzzle);
puzzle_1.display();
Unrelated to your question, but if maxRow or maxCol is larger than 3, then you will read from outside the memory for the array inputPuzzle. This will lead to undefined behavior.
The most important part here is the new keyword. It returns a pointer to the newly instantiated object. Check the Dynamic memory allocation for more information and to understand when and how to use pointers, and how the new keyword works.
Now, we know that the new keyword returns a pointer, and you want to obtain an object not a pointer, hence you have to dereference your pointer.
Two correct solutions now:
// without pointers
puzzle puzzle_1(inputPuzzle); // initialize the object without going through a copy
puzzle_1.display();
// with pointers
puzzle *puzzle_1 = new puzzle(inputPuzzle);
puzzle_1->display(); //notice that we used -> here as it's a pointer
// do stuffs here
delete puzzle_1; // free the memory

size of a list using pointer in C++

How to get size of a list using pointer ? I have the following piece of code. I put few integers inside and later, tried to get the size of the list.
#include <iostream>
#include <list>
using namespace std;
int main ()
{
list<int>* t;
for (int i=1; i<10; ++i)
{
t->push_back(i*10);
}
cout<<"size:\t"<<t->size()<<endl;
return 0;
}
You need to initialise the pointer to actually point somewhere. That could be a dynamically-allocated list using new (in which case you should be using a smart pointer of some description), or it could be some other object that already exists (in which case this is "point"less, isn't it?).
Better yet, don't use a pointer:
list<int> l;
for (int i = 1; i < 10; ++i)
l.push_back(i*10);
cout << "size:\t" << l.size() << endl;
You haven't allocated t. Write list<int>* t = new list<int>; or better unique_ptr<list<int>> t (new list<int>); if you are in c++11 . But in this case allocating list on the stack will work better anyway.

How are arrays stored and deleted in memory?

I made a 2D array on the heap of some objects:
Step (1)
Obj **arr = new Obj *[n];
for (int i=0;i<n;i++)
{
arr[i] = new Obj[n];
}
// so this creates 2D arr[n][n]...then when I delete it:
Step (2)
for (int i=0;i<n;i++)
{
delete [] arr[i];
}
delete [] arr;
So I'm still not sure what this delete does. Does it run the destructor of Obj and flag the OS telling it this is now available memory.
Now what I REALLY do not understand is that when I do Step (1) again (after I deleted), I get these objects initialized to weird values, yet this doesn't happen the first time I do it (all zero-initialized). Did I just get lucky the first time?
AFAIK, the following code will NOT give you weird values, no matter how many times you repeat deleting and newing.
#include <iostream>
using namespace std;
class Foo
{
public:
Foo(): val(-2) { cout << "ctor" << endl; }
~Foo() { cout << "dtor: " << val << endl; }
private:
int val;
};
int main()
{
Foo **arr = new Foo *[2];
for (int i = 0; i < 2; ++i)
arr[i] = new Foo[2](); // <- for builtin type, () is required to initialized to zero.
for (int i = 0; i < 2; ++i)
delete [] arr[i];
delete [] arr;
return 0;
}
Relevant post: Operator new initializes memory to zero
As to what happens to pointers after you delete them, please see this post: C - What happens to an array of pointers when the array is freed?
Your example lacks the declaration of Obj.
new[] allocates memory and calls the constructor of each element
If the constructor does not alter memory, you will see some random values - maybe zeros.
delete[] calls the destructor of each element previously allocated with new[] and deallocates the memory, finally.
In a debugging compilation the memory might be filled with some bytes indicating the deallocation.
Doing new[] right after the deallocation might show indicator bytes.

Filling array of pointers by function c++

Hello I have made class gabka and a function f1 to which I would like to pass an array of pointers to fill this array with gabka objects but I get weird error. How to correct it?
error:
cannot convert from gabka to int
the code :
#include <iostream>
using namespace std;
const int n = 4;
class gabka {
public:
float woda;
gabka(){
woda = 0;
}
void f1(gabka t[n]){
for(int i = 0; i < n; i++){
t[i] = new gabka();
}
}
};
int main() {
gabka** t = new gabka*[n];
return 0;
};
Your f1 function takes an array of gabka objects, and you are trying to assign a gabka* to each one of them. You need to decide what you want to pass to f1. For example,
void f1(gabka t[n]){
for(int i = 0; i < n; i++){
t[i] = gabka(); // assign default constructed gabkas
}
}
or
void f1(gabka* t[n]){
for(int i = 0; i < n; i++){
t[i] = new gabka();
}
}
In the latter case, bear in mind you have to call delete on all the elements of t.
It isn't clear what you are intending to do with your code, but, as a general rule, in C++ you should avoid raw pointers and manual dynamic allocation. Prefer standard library containers over dynamically allocates arrays or arrays of dynamically allocated objects.
t[i] = new gabka();
t is an array of gabka, not an array of gabka*.
Either change the declaration of t to be an array of gabka*, or fill it with gabka instances.