stack/heap... let me know if I'm right

Given this code:

1
2
3
4
5
6
7
8
9
void myFunction (int * a) {
	*a = 10;
}

int main () {
	int *b = new int;
	*b = 20;
	myFunction(b);
}


Am I right to think that both a and literal value 10 are stored in the stack (with a holding the memory address of the literal value 10)?
And also, is correct to say that b is stored in the stack while 20 is stored in the heap?

Thanks
The 10 is an r-value and the standard leaves it implementation dependent where it'll be stored:
http://stackoverflow.com/questions/34221287/how-rvalues-in-c-stored-in-memory
http://stackoverflow.com/questions/27841555/where-are-rvalues-stored-in-c

Your pointer initialization could also be shortened a bit and don't forget the delete:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

void myFunction (int * a) {//a on stack 
	*a = 10;
}

int main () {
	int *b = new int(20);//b on stack, now 20 on heap with a memory address
	//*b = 20;
	myFunction(b);
	std::cout << *b << "\n";//prints 10
	delete b;
}

> Am I right to think that both a and literal value 10 are stored in the stack
> And also, is correct to say that b is stored in the stack while 20 is stored in the heap?

No and no.

The language specification for C++ (as specified in the IS) is only concerned about the lifetime of an object (and the duration for which the storage for an object would be available). The IS uses an abstract concept called 'storage duration' for this.

In the example above, a has automatic storage duration. The life-time of the object begins when the function myFunction is called and ends when the function returns (the enclosing block is exited from). The standard does not have anything to say from where or how an implementation should allocate storage for the object.

On the other hand, the int represented by the literal 10 is a prvalue (pure rvalue); since a situation that requires the temporary materialization of this prvalue does not exist, it is typically not associated with any object.
http://en.cppreference.com/w/cpp/language/implicit_conversion#Temporary_materialization

Since when we talk about 'stack', 'heap' etc., we are referring to specific implementation details, to complete the picture, we would also have to consider the "as-if" rule.
http://en.cppreference.com/w/cpp/language/as_if

For instance, a compiler could (should) rewrite the program as:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

// this function has external linkage; it can't be removed (unless link-time optimisation is enabled)
void myFunction (int * a) { 

	*a = 10;
}

int main () {
        
        void* pv = ::operator new( sizeof(int) ) ;  // the int initialised with the value 20 is optimised away

	std::cout << 10 << "\n" ; // print 10 

        ::operator delete(pv) ;
}
matching new/delete can also be optimized away (since c++14) - clang does that in this case
Huh. I was going to ask about this before (incorrectly) assuming that it couldn't be removed because new could throw. I thought about it and decided that removing it would violate the as-if rule.

There is already at least one exception to the rule where copy operations may be omitted even when copies have observable effects. Does the ability to remove matching new/delete pairs imply that the compiler is free to change functions which may throw exceptions into functions which do not (by eliminating the useless code which might throw), or is this particular exception specific to new and delete?
Last edited on
mbozzi wrote:
is this particular exception specific to new and delete pairs?

yes, this is the second exception from the as-if rule: new/delete expressions can annihilate each other or get replaced by stack allocations and repeated new-expressions can be merged. There are some conditions where it can't be done:

cppreference: http://en.cppreference.com/w/cpp/language/new#Allocation
standard http://eel.is/c++draft/expr.new#10
Good to know - thank you.
Topic archived. No new replies allowed.