C++ pointers

Pages: 12
Jul 11, 2022 at 7:40am
Hello, my professor gave me this code and asked me to run it, but before that she said that I must remove all the asterisks in the codes and instruct me to use "typedef int* IntPtr" (idk what it is, i think its a library?) instead, by doing that she said that these codes will still run even if the asterisks are removed in the codes.

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

int main()
{
    int *p1, *p2;

    p1 = new int;
    *p1 = 42;
    p2 = p1;

    cout << "*p1 == " << *p1 << endl;
    cout << "*p2 == " << *p2 << endl;
    *p2 = 53;
    cout << "*p1 == " << *p1 << endl;
    cout << "*p2 == " << *p2 << endl;
    p1 = new int;
    *p1 = 88;
    cout << "*p1 == " << *p1 << endl;
    cout << "*p2 == " << *p2 << endl;


   return 0;
}
Last edited on Jul 11, 2022 at 7:43am
Jul 11, 2022 at 7:45am
typedef just creates an alternative name for a type.

 
typedef int* Ptr;

After this line of code you can write Ptr to denote the int* type.
Last edited on Jul 11, 2022 at 7:46am
Jul 11, 2022 at 7:46am
I tried this but it says redeclaration of 'int* p1 & p2'. Assuming all lines that has IntPtr contains asterisks before. (replaced).

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
#include <iostream>
typedef int* IntPtr;
using namespace std;

int main()
{
   IntPtr p1, p2;

    p1 = new int;
    IntPtr p1 = 42;
    p2 = p1;

    cout << "*p1 == " << IntPtr p1 << endl;
    cout << "*p2 == " << IntPtr p2 << endl;
    IntPtr p2 = 53;
    cout << "*p1 == " << IntPtr p1 << endl;
    cout << "*p2 == " << IntPtr p2 << endl;
    p1 = new int;
    IntPtr p1 = 88;
    cout << "*p1 == " << IntPtr p1 << endl;
    cout << "*p2 == " << IntPtr p2 << endl;

   return 0;
}
Jul 11, 2022 at 7:52am
Line 7 is correct. Are you sure this wasn't the only line where your professor wanted you to remove all asterisks?

The typedef won't help you remove the asterisks on the other lines. For that you would have to rewrite the code to not use pointers, or write a function that dereference the pointer and returns the result and call that in main instead (you would still have to use the asterisk inside the function definition).
Last edited on Jul 11, 2022 at 7:54am
Jul 11, 2022 at 7:55am
Ohh I see, I've been working on this for 3days. Could you fix this codes using typedef? I would like to see an example. Thanks mate :D
Jul 11, 2022 at 8:07am
No, I can't remove all asterisks by only using typedef.

That's why I'm wondering if you have understood what your professor has asked you to do correctly. Are you sure she didn't just want you to remove the asterisks from line 7?
Jul 11, 2022 at 8:10am
Removing all asterisks is of course possible, but not sure that's what your professor intended...

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;

int main()
{
    cout << "*p1 == " << 42 << endl;
    cout << "*p2 == " << 42 << endl;
    ...

Or maybe this is it. She just want you to step through the code in your head and replace everything with fixed values? That would force you to think about what is happening and hopefully learn more compared to if you had just ran the program and looked at the output.
Last edited on Jul 11, 2022 at 8:15am
Jul 11, 2022 at 8:44am
The instructions don't really make sense - as * is used in C++ for memory de-referencing. I suggest this is checked... Although * can be replaced with [0] to treat the memory pointer as a pointer to memory 'array' with 1 element. If this is what is meant this should have been made more clear as to requirements.

Also, in C++ using is usually used instead of typedef.

When memory has been allocated via new, it should be freed by using delete.

For the closest to not using * consider:

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

//typedef int* IntPtr;
using IntPtr = int*;

int main() {
	IntPtr p1 { new int { 42 } };
	IntPtr p2 { p1 };

	std::cout << "*p1 == " << 42 << '\n';
	std::cout << "*p2 == " << 42 << '\n';

	*p2 = 53;    // Needed to change the contents of the memory pointed to by p2
        //p2[0] = 53;    // If this is what is wanted... Who knows?
	std::cout << "*p1 == " << 53 << '\n';
	std::cout << "*p2 == " << 53 << '\n';

	p1 = new int {88};
	std::cout << "*p1 == " << 88 << '\n';
	std::cout << "*p2 == " << 53 << '\n';

	delete p1;
	delete p2;
}



*p1 == 42
*p2 == 42
*p1 == 53
*p2 == 53
*p1 == 88
*p2 == 53

Last edited on Jul 11, 2022 at 3:55pm
Jul 11, 2022 at 1:42pm
You can use [] instead of *.
cout << p1[0]
is the same as
cout << *p1

but who knows if this is what they want. You could ask your prof maybe?
I have no idea what they are trying to teach you here. The original code is more C than c++, leaks memory (line 17), encourages you to do something ugly (typedefs and usings should not rename basic types: use the C++ name so everyone can understand what it is) and has an unclear request that, even if we understand it, is not really driving home any kind of useful core concept.

I recommend you study learncpp.com to supplement this course, when you get a chance.
Jul 12, 2022 at 10:08am
Thanks everyone for the comments and helpful information you gave to me.
Jul 12, 2022 at 10:13am
jonnin wrote:
leaks memory (line 17)

Actually, it doesn't.
Jul 12, 2022 at 10:31am
leaks memory (line 17)


No - as p2 is now pointing to the memory allocated for p1. If p1 and p2 memory is now deleted (as per my code above) then there is no memory leak.
Jul 12, 2022 at 10:34am
The original code does leak memory. It uses new twice without using delete.
Jul 12, 2022 at 10:37am
Yes, it should use delete and obviously that is a good habit to get into.

But it doesn't leak memory, because the original memory allocated to p1 is still addressable via p2. The same use of new with pointers would arise if you were constructing a forward list and using new with the head pointer all the time.


Part of the issues with * arises because it is used both in the type declaration AND as a dereferencing operator in c++. Other languages use pointers as an alias and don't require a separate dereferencing operator.
Last edited on Jul 12, 2022 at 10:41am
Jul 12, 2022 at 10:44am
lastchance wrote:
it doesn't leak memory, because the original memory allocated to p1 is still addressable via p2.

But it will be leaked at the end of main, when both p1 and p2 go out of scope. You might not think of this as a problem but I would still consider it to be a memory leak although not on line 17 obviously.
Jul 12, 2022 at 10:53am
It's a matter of definition. For the duration of the original program the heap memory used remains accessible, so I don't regard it as a memory leak. It will be handed back to the operating system when the program ends.

Clearly it is good practice to have "one new - one delete". (But I don't always clear my linked lists after creating them. As long as they don't continually accumulate memory I let sleeping dogs lie.)
Last edited on Jul 12, 2022 at 10:55am
Jul 12, 2022 at 11:03am
But isn't the "duration of the program" continuing after main() has ended for a little while, to clear up static vars, run functions passed to std::atexit, etc.?

Anyway, I can see how leaking might be used as an "optimization" but the disadvantage is that it makes it harder to find the real leaks when using a memory leak detection tool such as valgrind.
Jul 12, 2022 at 11:11am
Well, the definition of "memory leak" has been a source of contention before!
https://stackoverflow.com/questions/312069/the-best-memory-leak-definition

IMO some of those answers are "leaking" into the valley of "best practice", rather than strictly defining memory leaks.

I certainly wouldn't use deliberate leaking as an "optimisation", but if "delete" is only going to appear as the last lines of a program - and any future editing of that program isn't likely to change that - then I don't always bother to put them there.
Jul 12, 2022 at 12:21pm
Most modern non-embedded os's free all allocated resources when a program terminates (including memory). So in most cases you do not actually have to free allocated memory before the program exists if it is not required to delete this memory elsewhere in the program. However I contend that it is good practice to do so. Program analysers can squawk if it doesn't and memory errors can be reported on delete. If the delete isn't present and the OS is reliant to delete it can be more difficult to trace a memory error. Also IMO it's a good habit to get into to always delete allocated memory - and not rely/assume about the OS.

Of course, in modern C++ you'd probably use std::unique_ptr/std::shared_ptr instead of new/delete, wouldn't you, in which the issue doesn't arise...
Last edited on Jul 12, 2022 at 12:36pm
Jul 12, 2022 at 12:26pm
It is a leak as far as this program is concerned; there is nothing contentious about that.

Whether the operating environment cleans up when the sloppy program exits depends: on almost all hosted environments, it would; on many freestanding implementations it won't.
Pages: 12