Reputation: 27
My class (let's call it A
) takes in a string::iterator
and it implements two methods:
auto peek() const -> const char &
: Returns a reference to the data at the current position.auto get() -> const char &
: Returns a reference to the data at the current position then increments the position.The solution I have come up with is the following:
class A {
std::string::iterator _s;
public:
A() = delete;
explicit A(std::string::iterator s) : _s(s) {}
auto peek() const -> const char & {
return *_s;
}
auto get() -> const char & {
return *(_s++); // <-- valid?
}
};
In this case, I understand returning a temporary copy of the value would also work since char
is small enough in size:
auto get2() -> char {
const auto c = *_s;
_s++;
return c;
}
However, say the data was sufficiently large enough such that I wanted to return a reference instead of copying. Would the following code be a valid way of doing this in C++?
auto get() -> const char & {
return *(_s++);
}
Upvotes: 2
Views: 144
Reputation: 595847
Yes, return *(_s++);
is perfectly valid and safe, provided s
is a valid iterator to begin with (ie, the string
is alive, and s
is within the string
's valid iterator range).
_s++
will increment s
, returning a new iterator
that is a copy of s
before it was incremented.
Then *
dereferences that copied iterator
, yielding a non-const char&
reference to the char
that s
originally referred to within the string
.
You then return
that reference as-is to the caller as a const char&
reference, which is perfectly fine.
Even if you did not want to trust this logic, your approach to use a local variable is fine, and you can return a reference by simply declaring that variable as a reference rather than a value, eg:
auto get() -> const char & {
const char &c = *_s;
++_s;
return c;
}
Upvotes: 3