Question on class pointers...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>

using namespace std;

class MyClass{
public:
    int nValue;

};


int main()
{

    MyClass* pMC[5];

    for (int i=0; i<5 ; i++){
        pMC[i]->nValue = i;
        cout << pMC[i]->nValue;
    }

    return 0;
}


The code above doesn't work, it compiles and runs but goes berserk and crashes. I can't understand why.

The following variations work:

1
2
3
4
5
6
    MyClass pMC[5];

    for (int i=0; i<5 ; i++){
        pMC[i].nValue = i;
        cout << pMC[i].nValue;
    }


1
2
3
4
5
6
7
8
9
    
    MyClass* pMC = new MyClass[5];

    for (int i=0; i<5 ; i++){
        pMC[i].nValue = i;
        cout << pMC[i].nValue;
    }
    delete[] pMC;
    


From what I know of pointers and arrays, the first variation makes logical sense to me so i don't understand why it crashes. In english I would translate it to "pMC is an array of pointers which point to objects of type MyClass". I'm assuming I'm wrong. Any insight would be appreciated.
Last edited on
closed account (D80DSL3A)
pMC is an array of pointers which point to objects of type MyClass

You have an array of pointers, but they haven't been pointed to anything yet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{

    MyClass *pMC[5];
    cout << "pMC: " << pMC << endl;
    cout << "pMC[0]: " << pMC[0] << endl;
    cout << "pMC[0]->nValue: " << pMC[0]->nValue << endl;

    for (int i=0; i<5 ; i++){
        pMC[i]->nValue = i;
        cout << pMC[i]->nValue << endl;
    }

    return 0;
}


pMC: 0x7fff2ddaf5f0
pMC[0]: 0x2
Segmentation fault (core dumped)

So, pMC[i] do not point to right memory. And now this one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{

    MyClass *pMC[5]{new MyClass, new MyClass, new MyClass, new MyClass, new MyClass};

    for (int i=0; i<5 ; i++){
        pMC[i]->nValue = i;
        cout << pMC[i]->nValue << endl;
        cout << "pMC: " << pMC << endl;
        cout << "pMC[" << i << "]: " << pMC[i] << endl;
        cout << "pMC[" << i << "]->nValue: " << pMC[i]->nValue << endl;
    }

    return 0;
}


0
pMC: 0x7fff2c5ddd60
pMC[0]: 0x163c010
pMC[0]->nValue: 0
1
pMC: 0x7fff2c5ddd60
pMC[1]: 0x163c030
pMC[1]->nValue: 1
2
pMC: 0x7fff2c5ddd60
pMC[2]: 0x163c050
pMC[2]->nValue: 2
3
pMC: 0x7fff2c5ddd60
pMC[3]: 0x163c070
pMC[3]->nValue: 3
4
pMC: 0x7fff2c5ddd60
pMC[4]: 0x163c090
pMC[4]->nValue: 4


P.S. I use C++11
P.S.S but this code creates a memory leak. At the end you need to use.
1
2
3
4
5
delete[] pMC[0];
    delete[] pMC[1];
    delete[] pMC[2];
    delete[] pMC[3];
    delete[] pMC[4];
Last edited on
Thanks for replies... So the problem is the first statement "MyClass* pMC[5];". Why is it that it doesn't point to valid memory? Is this just something I'm going to have to accept or is there a logical reason for it? As you might have guessed I don't like just accepting things as they are that don't appear logical to me. :p

If I swap the arrays with normal variables:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{

    MyClass* a;



    for (int i=0; i<5 ; i++){
        (*a).nValue = i;
        cout << (*a).nValue;
    }

    return 0;
}


This program works just fine. How come 'a' points to valid memory and the array doesn't? Why is it that I must use memory off the heap in order for the array-version to work?
Last edited on
closed account (zb0S216C)
zukias wrote:
"Why is it that it doesn't point to valid memory?"

...because you're not initialising the pointers to a valid address. An uninitialised pointer is called a wild pointer because it [the pointer] can be referring to any address in memory, even if the memory it points-to is unowned by your program. Attempting to dereference an uninitialised pointer results in undefined behaviour. Also, I don't know if you realise it, but you're declaring an array of pointers, not "MyClass" instances.

zukias wrote:
"This program works just fine."

Your program invokes undefined behaviour with every execution. The program may run fine, but don't expect that behaviour every time you run the program.

zukias wrote:
"How come 'a' points to valid memory and the array doesn't?"

"a" is not pointing to valid memory. Just because you can dereference a pointer without causing the program to crash does not mean the pointer to pointing to valid memory; again, undefined behaviour.

zukias wrote:
"Why is it that I must use memory off the heap in order for the array-version to work?"

A pointer to some type must refer to some valid object, but an array creates a series of valid objects, regardless of whether or not the memory for the objects was allocated statically or dynamically.

Wazzak
Last edited on
ok so it seems like you're just starting to step into the wonderful world of pointers. Welcome, it only gets better from here.

The first thing you need to always remember is that where there is a * (pointer) there needs to be a new and delete accompanying that pointer.

In regards to your last question the reason the first value contains of a contains memory is because you've only declared a single pointer, not an array. So everything there after is garbage. Also, you're dereferencing the pointer to object level and making an assignment. If you were not dereferencing ( (*a) ) I'm pretty sure you will get an error thrown.

Keep in mind that the ' . ' operator is accessing variables as an object and ' -> ' is accessing information from a pointer (dynamic memory)


Here's a complete example that will work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>

using namespace std;

class MyClass{
public:
	MyClass() {}
	int nValue;
};

int main()
{
	int size;
	cout << "Size of array: " << endl;
	cin >> size;

	MyClass **MyClassList;
	MyClassList = new MyClass*[size];

	for(int i = 0; i < size; i++)
	{
		MyClassList[i] = new MyClass();
		MyClassList[i]->nValue = i;
	}

	for(int i = 0; i < size; i++)
	{
		cout << MyClassList[i]->nValue << endl;
	}

	system("pause");

	delete[] MyClassList;

	return 0;
}


You really need to be aware that having an array of pointers is allocated like in my above example. If you do not have the double ** it is simply just a dynamic array of objects.

No leaks were reported after running this example.

@Shinigami

P.S. I use C++11

Good!

P.S.S but this code creates a memory leak. At the end you need to use.

delete[] pMC[0];
delete[] pMC[1];
delete[] pMC[2];
delete[] pMC[3];
delete[] pMC[4];


You're mixing two different things there. delete[] delete dynamic pointer arrays. So the correct syntax for clearing the memory to prevent a leak would be:

 
delete[] pMC;


What you're demonstrating is more along the lines of individually deleteing each index of memory allocation. So you're solution is more like this:

1
2
3
4
5
delete pMC[0];
delete pMC[1];
delete pMC[2];
delete pMC[3];
delete pMC[4];


References:
Experience
http://www.cplusplus.com/forum/general/20044/
http://www.cplusplus.com/doc/tutorial/dynamic/
Last edited on
Thanks for replies anthony & framwork, I think that cleared it up for me :)

So to summarize, from what I understand now; the pointers cause erratic behaviour at execution because the addresses they hold that are being dereferenced are undefined (since the pointers haven't been initialized).

I ask because often pointers seem to defy logic and what I seem to think I understand about them is actually later revealed to be wrong. :P
Last edited on
Topic archived. No new replies allowed.