-1

I tried to figure out how new works:

#include <iostream>
using namespace std;

struct munch{
    int x;
};

int main(){
    munch *a;
    //1
    cout << a << endl;
    cout << a->x << endl;
    //1
    cout << endl;
    //2
    a= new munch;
    cout << a << endl;
    cout << a->x << endl;
    //2
    cout << endl;
    //3
    a= new munch;
    cout << a << endl;
    cout << a->x << endl;
    //3
}

What's the difference between 1, 2 and 3? Why does the operator new gives the pointer to struct a new location but doesn't change the value of a->x? But before calling the first instance of new it has a different value than after calling new once?

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
Samuel Cota
  • 57
  • 1
  • 2
  • 6

7 Answers7

2

[1] is undefined behavior as it's trying to de-reference uninitialized pointer.

[2] and [3] are same and could result in undefined behavior although at the least you would get garbage values for your fields in struct.

More on [2] and [3] from what Standard says:-

The C 1999 standard says, in 6.7.8 10, “If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.”

Also, If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

ravi
  • 10,994
  • 1
  • 18
  • 36
  • 1
    Trying to read an uninitialized variable is not at all "well-defined". `cout << a->x << endl;` is undefined behavior. – wolfPack88 Dec 31 '14 at 14:54
2

In the first case, you're reading an uninitialized pointer, which is undefined behaviour (both a and a->x are undefined).

What's important in the other two examples is that munch is Plain Old Data. This means that new munch does not initialize the fields of the newly allocated struct. Therefore, reading a->x also results in undefined behaviour.

This being C++, you could add a constructor to munch that would initialize x and make examples 2 and 3 well-defined.

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
2

In 1, you have declared a pointer to munch, but have not initialized it. Therefore, both cout << a << endl; and cout << a->x << endl; is undefined behavior, as they have not been initialized. In both 2 and 3 (can't find a difference between the two in terms of code), the first line cout << a << endl; is now defined behavior, as you have assigned a memory address to a via a = new munch;. However, a->x is still uninitialized (you never set it by using something like a->x = 5;), so cout << a->x << endl; is still undefined behavior in both cases.

wolfPack88
  • 4,163
  • 4
  • 32
  • 47
1

First, let's clarify your semantics.

Be aware that there is both a new-expression in the language, and an operator new.

There are various forms of operator new defined, like the placement one, the non-throwable global ones and the replaceable global ones.

A new-expression consists of calling one of those allocation-functions, and then doing any initialization indicated.
If the second part fails, it will also call the corresponding de-initialization function.

So, let's take a look what you have:

In case one, just reading an uninitialized non-static (thus indeterminate) pointer is Undefined Behavior.

In case 2 and 3, because munch is a POD-type, your new-expression does not result in a constructor-call, meaning all members stay uninitialized, thus reading munch::x is UB.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
0

Because the value of x is a garbage value, since you don't initialize it anywhere. And the first value of a is also garbage, you didn't point with it anywhere either.

The new operator request a memory segment from the operating system and calls the class constructor, returning a pointer to that memory and storing it's address in the variable.

Since munch has no constructor then it's never initializing x.

All your code has, undefined behavior, so you should never do things that way, the correct way of using the munch struct with dynamic memory allocation is

munch *a;

a = new munch;
a->x = SOME_INITIAL_VALUE;

std::cout << "address of a : " << a << std::endl;
std::cout << "value of a->x: " << a->x << std::endl;

Or add a constructor to your struct, where you can initialize x

struct munch 
{
    public:
        munch(int initial_x = SOME_INITIAL_VALUE) : x(initial_x) {}
        int x;
};

munch *a;

a = new munch;

std::cout << "address of a : " << a << std::endl;
std::cout << "value of a->x: " << a->x << std::endl;
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
0

When you declare a variable struct munch, what compiler does is, it simply takes the chunk of memory of size equivalent to sizeof(munch) and assigns it a name that you have given.

But in case of pointer declaration, compiler simply gives a name to a memory location and doesn't allocate any memory until you specify it explicitly(using new operator).

For ex :

munch *a;

This statement will simply assign a name a to a memory location. So, cout<<a will print that memory address.

When you do cout<<a->x it will give you run-time error, because you haven't allocated space. So you don't have any value right now.

//2

First of all new memory location will be given where a will point. And memory will be allocated due to new operator. And variables inside the struct will have default values that are already there at the memory location allocated.

So, when you do cout<<a, it will print new location of a. And when you do cout<<a->x, it will now give some random value. If you compile & run the program again and again, you might get different values each time.

//3

Like case #2, same thing will happen. First of all, new memory location will be selected and a will point to that location. Then you results will be printed but the values might be different then case #2 due to different memory location.

shreyans800755
  • 244
  • 1
  • 10
0

the new operator allocates memory for the instance on the heap and returns the pointer. for your code, 1. allocates an item on the stack. 2 and 3 allocate items on the heap. when i run the code you provided, i get a different value for x in all 3 instances (CodeLite/MingGW) :

0x417d7e

1528349827

0x8f6bd8

12

0x8f6be8

14

every new should accompany a delete.

Mark Lybarger
  • 463
  • 3
  • 9