c++ assign a 2D array to an Object - c++

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

Related

Dynamic array of pointers, how to do it correctly?

I know, I could use std::vector or something like that, but I want to know where I think wrong. In the example below, only p3 is in my eyes really a pointer to an array of pointers and is used in the way I would expect. Using p1 instead looks kind of wrong to me because it looks like p1 is also an array of pointers like p2 is and not a pointer to an array of pointers, except for the delete thing. So when I try to use p2 as I do use p3:
(*p2)[i] = new Foo(i);
the error is:
ambiguous overload for ‘operator=’ (operand types are ‘Foo’ and ‘Foo*’)
The question is:
Why do I have to use a cast in the line where p3 is allocated?
Is that assignment for p3 correct or does it just work by incident?
#include <iostream>
using namespace std;
class Foo
{
public:
Foo (int key)
: key(key)
{}
int show() const
{
return key;
}
private:
int key;
};
int main (int, char**)
{
int aSize = 10;
using FooP = Foo *;
FooP *p1 = new FooP[aSize];
FooP p2[aSize];
FooP (*p3)[] = (FooP (*)[]) new FooP[aSize];
for (int i=0; i < aSize; i++)
{
p1[i] = new Foo(i);
p2[i] = new Foo(i + aSize);
(*p3)[i] = new Foo(i + aSize * 2);
}
for (int i=0; i < aSize; i++)
{
cout << p1[i]->show() << ", "
<< p2[i]->show() << ", "
<< (*p3)[i]->show()
<< endl;
delete p1[i];
delete p2[i];
delete (*p3)[i];
}
cout << endl;
delete [] p1;
delete [] p3;
return 0;
}
So the explanation is, that the operator "new" in case of an array, always returns a pointer to the first element and not, as I expected, a pointer to the array of pointers.
So the cast I used when assigning the allocated memory to the variable p3 is valid and would not cause any memory corruption, right?
Thanks to #exprosic for the helpful hint in the comments to https://en.cppreference.com/w/cpp/language/new
Quote from there:
The new expression attempts to allocate storage and then attempts to construct and initialize either a single unnamed object, or an unnamed array of objects in the allocated storage. The new-expression returns a prvalue pointer to the constructed object or, if an array of objects was constructed, a pointer to the initial element of the array.

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.

I allocate memory for a Pair object but fail to place the object there

I would like to have a dynamic array of pointers to pointers to Pair elements;
int m_size = 0;
Pair** ar = new Pair*[++m_size];
*ar[0] = Pair(key, data);
Here I get:
Unhandled exception at 0x013729db in lab3.exe: 0xC0000005: Access violation writing location 0xcdcdcdcd.
It happened in the overloaded operator for MyString (HERE marks when the exception threw):
MyString & MyString::operator = (const MyString & refMyString){
HERE: this->m_pStr = refMyString.m_pStr;
return *this;
}
My classes (a bit simplified for our purpose):
class Pair{
MyString m_key;
Data* m_data;
}
class MyString
{
char* m_pStr;
}
And here is what I get in the debugger:
http://sdrv.ms/ZwkZ9P
http://sdrv.ms/17eoGp6
Well, as far as I can see, when I did Pair** ar = new Pair*[++m_size], a new pointer to pointer to a space for a Pair instance was created. But it is just space in memory. And when I try to operate it, I fail.
And what to do is a mystery to me. Could you help me?
You allocate an array of Pair* but :
1) You never initialize the pointers in that array
2) You dereference those uninitialized pointers (which point to who-knows-where) and overwrite the memory there.
No wonder you get a segfault since you're writing to unallocated memory.
What you (probably?) want to do is:
ar[0] = new Pair(...)
Or better yet, use a standard container (vector, list, deque, ...) instead of C arrays, that will either contain plain objects or smart pointers (unique_ptr or shared_ptr) so that you don't have to manage the memory yourself.
When creating a two dimensional array using a double pointer, you need to allocate both dimensions:
// allocates an array of 10 int* objects
int** p = new int*[10];
for(int x = 0; x < 10; ++x)
{
// Allocates an array of 3 integers
p[0] = new int[3];
}
You would need to ensure that all of the objects you are creating are deleted:
// later
for(int x = 0; x < 10; ++x)
delete [] p[x];
delete [] p;
I would suggest however, just using std::vector so you don't need to manage the memory yourself:
std::vector<std::vector<int>> p;
p.resize(10);
for(int x = 0; x < 10; ++x)
{
p[x].resize(3);
}

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.

C++ public constructor address

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.