I'm studying some C features, trying to play around with some experiments. However, I stuck in a place where it compiled error:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "some string";
auto &c = str.begin(); // compile error
*c = toupper(*c);
cout << *c << ", str: " << str << endl;
}
I'm not sure why it was not acceptable. My thought was that c
had type char *
(a pointer to a char
), so that's why I had written as above. But why it failed in compiling?
Error C2440 Cannot transform 'std::_String_iteratorstd::_String_val<std::_Simple_types<_Elem>>' to'std::_String_iterator<std::_String_val<std::_Simple_types<_Elem
PS: Another method which I had tried first was OK.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str = "some string";
auto &c = *str.begin(); // success
c = toupper(c);
cout << c << ", str: " << str << endl;
}
CodePudding user response:
begin()
returns an iterator by value, not a reference. You are not allowed to form a non-const
lvalue reference.
Making it const
would prolong the life of the returned iterator and the program would then compile:
const auto &c = str.begin();
On the other hand, iterators are supposed to be cheap to copy and iterators from contiguous containers are often implemented as pure pointers. The idiomatic approach is:
auto c = str.begin();
In your second example, the idiomatic approach to form a reference to the first element would be:
auto& c = str.front();