nik
nik

Reputation: 27

Is this a valid way to return an iterator element and post-increment?

My class (let's call it A) takes in a string::iterator and it implements two methods:

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

Answers (1)

Remy Lebeau
Remy Lebeau

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

Related Questions