Function that returns a reference, a pointer, or a reference to a pointer?

I'm having issues with my functions that return both a reference and a pointer and reference pointer. On visual studio if I try displaying these or really doing anything with the pointers/references it crashes. Not only that but it will give me this mumbo jumbo output as well. However on cpp.sh it will give me the correct output, well for all of them but one. And that one is the NewPointerValue that is obtained from GetNewPointerRef(), because on cpp.sh if I try displaying it crashes the program. Something worth mentioning as well is that if I try to delete ANY of them it crashes and I have no clue why?

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
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
using namespace std;
double *& GetNewPointerRef() {
    double val = 1337.1337;
    
    double* pointer = new double;
    pointer = &val;
    return pointer;
}
double *& GetStaticPointerRef() {
	double n = 1550.85;

	static double* v = &n;
    
	return v;
}
double* GetPurePointer() {
    double n = 1337.1337;
    
    double* pointer = new double;
    pointer = &n;
    return pointer;
}
double& GetReferenceOnly() {
    double val = 0.1;
    double* pointer = new double;
    pointer = &val;
    return *pointer;
}
int main()
{
    double StaticNumberPointerValue = *GetStaticPointerRef();
    double& NewPointerValue = *GetNewPointerRef();
    double *PurePointerValue = GetPurePointer();
    double &ReferenceValueOnly = GetReferenceOnly();
    cout << "StaticNumberPointerValue: " << StaticNumberPointerValue << endl;
    cout << "----------------------------------\n";
    /*cout << "NewPointerValue: " << NewPointerValue << endl;
    cout << "----------------------------------\n"; The above lines crashes the program*/
    cout << "PurePointerValue: " << *PurePointerValue << endl;
    cout << "----------------------------------\n";
    cout << "PureReferenceValueOnly: " << ReferenceValueOnly << endl;
    cout << "----------------------------------\n";
    
    delete PurePointerValue;
    delete& ReferenceValueOnly;
    return 0;
}


Also I was wondering which one would be the better of the three. I've asked a similar question before on a function that returns a pointer however I learned that you could do either one. In which I was planning on most likely encapsulating the return value into a smart pointer.
cpp.sh says:
 In function 'double*& GetNewPointerRef()':
6:13: warning: reference to local variable 'pointer' returned [-Wreturn-local-addr] 

Indeed. The GetNewPointerRef() returns a reference to local variable (in stack memory) 'pointer'. A reference to an object that does not exists after the function returns.

Lines 7, 21, and 27 are memory leaks. You write to pointers that hold addresses of dynamically allocated memory. You cannot deallocate that memory when you no longer have address stored anywhere.

The GetStaticPointerRef() returns a reference to static local variable. That is not so bad, but the variable is a pointer and holds the address of local variable (in stack memory) 'n'. Again, an object that does not exists after the function returns. You get a reference to pointer that contains invalid address.

The GetPurePointer() is a variation of the above. You get a copy of a pointer. (That is fine.) The address stored in the pointer is of local variable (in stack memory) 'n'. Again, an object that does not exists after the function returns. You get a pointer that contains invalid address.

The GetReferenceOnly() returns reference to local variable 'val'. You should know the drill by now.

All your functions invoke undefined behaviour.

Finally, lines 45-46 attempt to delete addresses that are no in Free store.


I was wondering which one would be the better of the three.

That depends entirely on the problem.
Indeed. The GetNewPointerRef() returns a reference to local variable (in stack memory) 'pointer'. A reference to an object that does not exists after the function returns.

Wow I had a complete brain fart when writing that code. I made it a pointer so it would live outside of the scope but I forgot that the variable it was holding would go out of scope making that pointer useless and causing a whole load of other problems. Makes a lot of sense now.

Lines 7, 21, and 27 are memory leaks. You write to pointers that hold addresses of dynamically allocated memory. You cannot deallocate that memory when you no longer have address stored anywhere.

Understood completely forgot about those variables scopes some how.

I edited so that it is now allocating memory for a class object rather than a primitive. Anyways why is line 9 giving me a warning? I'm returning a pointer that was allocated on the heap and well it's not storing any other address. Also I'm getting two more errors well problems in the program with the getstaticpointer and getnewpointerref. And the problem is they crash the problem. However I think it's because I'm trying to dereference them and well the compiler doesn't how I want to dereference them and it crashes the program. I assume I would have the overload derefencing operator to get that to work. Anyways if that is the error which I think it is, why doesn't cpp.sh throw an error telling it me can't do that? I'm not saying it's the compilers fault or anything for my code but I'm just curious as to why?
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
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <memory>
using namespace std;
class storage {
public:
    double value;
};
storage *& GetNewPointerRef() {
    storage* pointer = new storage;
    pointer->value = 10.0;
    return pointer;
}
storage *& GetStaticPointerRef() {
	static storage* v;
	v->value = 1550.85;
    
	return v;
}
storage* GetPurePointer() {    
    storage* pointer = new storage;
    pointer->value = 1337.1337;
    return pointer;
}
storage& GetReferenceOnly() {
    storage* pointer = new storage;
    pointer->value = 60.75;
    return *pointer;
}
int main()
{
    //storage StaticNumberPointerValue = *GetStaticPointerRef();
    //storage& NewPointerValue = GetNewPointerRef();
    storage *PurePointerValue = GetPurePointer();
    storage &ReferenceValueOnly = GetReferenceOnly();
    //cout << "StaticNumberPointerValue: " << StaticNumberPointerValue.value << endl;
    //cout << "----------------------------------\n";
    //cout << "NewPointerValue: " << NewPointerValue.value << endl;
    //cout << "----------------------------------\n";
    cout << "PurePointerValue: " << PurePointerValue->value << endl;
    cout << "----------------------------------\n";
    cout << "PureReferenceValueOnly: " << ReferenceValueOnly.value << endl;
    cout << "----------------------------------\n";
    
    delete PurePointerValue;
    delete& ReferenceValueOnly;
    char response;
    cin >> response;
    return 0;
}
I'm returning a pointer that was allocated on the heap

No you're not. Let's look at it:
storage* pointer = ...

The pointer here, named pointer, is clearly not on the heap. What it's pointing to is on the heap, but the pointer isn't. The pointer is on the stack, and will cease to exist when the function ends.




1
2
3
4
5
6
storage *& GetStaticPointerRef() {
	static storage* v;
	v->value = 1550.85;
    
	return v;
}
The problem with this function? Tell me, what is that pointer v pointing at?
Last edited on
Furthermore, there is no difference between a class object and a primitive:
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
double * & GetNewPointerRef() {
    double * pointer = new double {10.0};
    return pointer; // reference to local variable
}

double * & GetStaticPointerRef() {
	static double * v; // uninitialized pointer;
	*v = 1550.85; // error, v is invalid
	return v; // returns reference to v (but v is static object, so does not vanish)
}

double * GetPurePointer() {    
    double * pointer = new double {1337.1337};
    return pointer; // ok
}

double & GetReferenceOnly() {
    double * pointer = new double {60.75};
    return *pointer; // ok?, reference to dynamically allocated object
}

// I've heard of some new kids in the block:

std::shared_ptr<double> foo() {
    return std::make_shared<double>( 3.14 );
}

std::unique_ptr<double> bar() {
    return std::make_unique<double>( 2.718 );
}

Furthermore, there is no difference between a class object and a primitive:

Oh I think I read some where that said that or something but might have been for a different language but alright.
double * & GetStaticPointerRef() {
static double * v; // uninitialized pointer;
*v = 1550.85; // error, v is invalid
return v; // returns reference to v (but v is static object, so does not vanish)
}

Ahh okay that makes sense why it would crash/cause undefine behavior in the program.

// I've heard of some new kids in the block:

std::shared_ptr<double> foo() {
return std::make_shared<double>( 3.14 );
}

std::unique_ptr<double> bar() {
return std::make_unique<double>( 2.718 );
}

Haha I didn't know you could do that with a smart pointer? I always thought their scope would die, thus losing the data you wanted to retrieve from them. I was planning on using them to retrieve the data/encapsulate it. Well that is cool to know that I can do that.
No you're not. Let's look at it:
storage* pointer = ...

The pointer here, named pointer, is clearly not on the heap. What it's pointing to is on the heap, but the pointer isn't. The pointer is on the stack, and will cease to exist when the function ends.

Ah okay I believe I understand now.

So pretty much its contents are on the heap, but the variable "pointer" itself is simply on the stack is only pointing to those contents on the heap and will go away but it contents will stay in memory.


storage *& GetStaticPointerRef() {
static storage* v;
v->value = 1550.85;

return v;
}
The problem with this function? Tell me, what is that pointer v pointing at?

If I understood it correctly pointer v has not been made dynamically so its contents are on the stack will go away with the pointer as well?
Last edited on
If I understood it correctly pointer v has not been made dynamically so its contents are on the stack will go away with the pointer as well?

Pointer is a variable that stores a value, just like any variable. The value is a memory address. The value can be invalid. Value nullptr is know to be invalid. Pointer has dereference operators to access object at the address.

Reading from invalid address is undefined behaviour, because it is not likely to contain valid object of expected type.
Writing to invalid address is undefined behaviour, because it overwrites something.
1
2
3
4
5
storage *& GetStaticPointerRef() {
  static storage* v; // uninitialized pointer
  v->value = 1550.85; // error, v is invalid, there is no storage
  return v;
}

If you had a storage object, it would be in some block of memory. The storage has member value. It is within that block of memory. The block starts at some address X. The value starts at X+offset. (The offset can be 0.)
Your v->value thus looks up from the definition of storage that value should be a double and is at offset relative to start of storage object. However you have not stored any value in v and thus the v->value refers to unknown address (+offset).

When you write "contents of pointer" you actually mean "the object that the pointer points to". Should mean.
Pointer is a variable that stores a value, just like any variable. The value is a memory address. The value can be invalid. Value nullptr is know to be invalid. Pointer has dereference operators to access object at the address.


Yeah I understand that. Kind of off topic but not really, maybe I should make this into another topic, but I usually understand things in the code like what it is doing it's just that I have a hard time expressing them correctly and thoroughly and well yeah.

Reading from invalid address is undefined behaviour, because it is not likely to contain valid object of expected type.
Writing to invalid address is undefined behaviour, because it overwrites something.


What I meant in the original quote you are referencing is that the problem with that variable was that it was not initialized and that it should have actually been
static storage*v = new storage
so that it could have been initialized. But that does help to explain it more thoroughly and clear some things up.

If you had a storage object, it would be in some block of memory. The storage has member value. It is within that block of memory. The block starts at some address X. The value starts at X+offset. (The offset can be 0.)
Your v->value thus looks up from the definition of storage that value should be a double and is at offset relative to start of storage object. However you have not stored any value in v and thus the v->value refers to unknown address (+offset).


Yeah that makes sense since the variable hasn't been initialized and its memory not allocated. So who knows what value v->value is pointing too since it has not been reserved specifically for it self, I got it.


When you write "contents of pointer" you actually mean "the object that the pointer points to". Should mean.


Yeah that makes more sense and clear things up.

Thanks!

Topic archived. No new replies allowed.