references

hi guys I must be mistaken,as I thought references are aliases to other variables of the same type so I'm not sure why this code won't work,now I know this is a bad idea because when readDiary() function ends entries goes out of scope and the entries in main will refer to memory that is not what you think it is.

anyway I still thought that this code should atleast compile but nope,

I am setting entries in main as a reference to entries from readDiary() but I am getting a compile time error

I'm not even sure how to decypher or what it means


cannot bind non-const lvalue reference of type 'std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >&' to an rvalue of type 'std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >'

sorry I'm rambling at this point,anyway the question is why isn't this possible?

thanks

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  map<string,string> readFromDiary(){

	map<string,string> entries;
	ifstream in;
	string date;
	string description;
	string fileName = "diary2.txt";

	in.open(fileName);

	if (!in.is_open()) {

		cout << "file could not be opened" << endl;
		return map<string,string>();
	}

	while (in) {

		getline(in, date, ':');
		getline(in, description);
		if (!in) {
			break;
		}
		entries[date] = description;
	}
	in.close();
	return entries;
}


void openDiary(){




}

void options(){

	cout << "MY DIARY" << endl;
	cout << "Press 1 - to add entry" << endl;
	cout << "press 2 - to view entries" << endl;
	cout << "press 3 - to quit" << endl;
}

int main() {

	bool quit = false;


	string hello = "";
	string hi = "hi";

	int a = 6;
	int &b = a;
	cout << sizeof(hello) << endl;
	cout << sizeof(hi) << endl;

	while(!quit){

		map<string,string> &entries = readFromDiary();
		options();
		int choice;
		cin >> choice;

		switch(choice){

		case 1: inputToDiary();
		break;
		case 2:
		for (map<string, string>::iterator it = entries.begin();
					it != entries.end(); it++) {

			cout << it->first;
			cout << it->second << endl;
			}
		break;
		case 3: quit = true;
		break;
		default: cout << "invalid choice" << endl;
	}

	}

}
You admit that you know it to be bad idea, but still wonder why the compiler agrees with you?
the question is why isn't this possible?
Because return entries; returns a temporary object, and you can't have a non-const reference of a temporary object.
https://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object
hi guys thanks for the replies,after reading the link above,

what do you mean by

you can't have a non-const reference of a temporary object.


because even if I make the reference a const

const map<string,string> &entries = readFromDiary();

I still get an error


edit*****

hi guys it seems that the error now has gone away BUT now I am getting a new error with my iterator,

anyway two questions


how come it the reference has to be const in order for this to work?

and also why am I getting an error with my iterator?


conversion from 'std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::const_iterator {aka std::_Rb_tree_const_iterator<std::pair<const std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> > >}' to non-scalar type 'std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::iterator {aka std::_Rb_tree_iterator<std::pair<const std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> > >}' requested

thanks


thanks
Last edited on
You shouldn't be getting the same error. Now the error would be that you're trying to use a non-const iterator to iterate over a const object. You have to make the iterator a const_iterator.

But this is divergent from the point... why don't you just return by value, and make it
map<string,string> entries = readFromDiary();?
or,
const map<string,string> entries = readFromDiary();
if you don't plan to modify it.

What are you trying to accomplish by making it a reference? As keskiverto said, you know this stems from a bad idea. It will technically work, but you're not doing yourself any favors by making the code look more complicated.
https://books.google.com/books?id=PSUNAAAAQBAJ&pg=PA191&lpg=PA191#v=onepage&q&f=false

Edit (for your edit):
how come it the reference has to be const in order for this to work?
One answer to this would be that it has to because the C++ standard says it has to.
As Stroustrup said in his book,

The initializer for a const T& need not be an lvalue or even of type T. In such cases:
[1] First, implicit type conversion to T is applied if necessary.
[2] Then, the resulting value is placed in a temporary variable of type T.
[3] Finally, this temporary variable is used as the value of the initializer



Another reason is that it allows you to take in a temporary object or an actual reference as the input parameter to a function.

1
2
3
4
5
6
7
8
9
void foo(int& a)
{
    a = 4;
}
int main()
{
    foo(3); // won't work because 3 is a temporary
            // it doesn't have an actual address that can be referenced.
}


1
2
3
4
5
6
7
8
9
10
11
void foo(const int& a)
{

}
int main()
{
    foo(3); // will work because this is equivalent to doing the following under the hood:

    int temp = 3;
    foo(temp);    
}
Last edited on
Thanks Ganado much appreciated =)

just a side note I made my iterator a const_iterator but since once the readDiary() function ends and entries in that function goes out of scope I thought my program would have crashed but it still works fine
Last edited on
Yep, you're welcome. It doesn't crash because doing
 
const map<string,string>& entries = readFromDiary();

is equivalent to
1
2
map<string,string> temp = readFromDiary();
const map<string,string>& entries = temp;


The map from readFromDiary() is deep copied into temp, and then entries is a const reference to temp.
If you bind a const reference to a temporary, then it extends the lifetime of that temporary.

(Specifically, this happens when the const reference is on the stack.)

See, for example:

https://stackoverflow.com/questions/11560339/returning-temporary-object-and-binding-to-const-reference?noredirect=1&lq=1

for more info.
Topic archived. No new replies allowed.