std::move_i...perator*,->(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… std::move_iterator::operator*,-> β€” the cute lil deref duo

okay bestie, so this page is straight outta the C++ Standard Libary manual (yes that's how the header spells it, I don't make the rules πŸ’€) and it's all about two tiny member functions on std::move_iterator that hand you your elements with move energy instead of copy energy. main character behavior, honestly.


✨ Synopsis ✨

reference operator* () const; (1) (since C++11)
                                  (constexpr since C++17)
                                  (since C++11)
pointer operator->() const;   (2) (constexpr since C++17)
                                  (deprecated in C++20)

So what do they do? They return you an rvalue-reference or a pointer to the current element. That's the whole vibe check πŸ’–

  1. It's equivalent to static_cast<reference>(*base()) (until C++20), and equivalent to ranges::iter_move(base()) (since C++20).
  2. It's equivalent to base().

🌸 Parameters 🌸

  • (none) β€” nothing, nada, zero args, she takes no notes πŸ“­

πŸŽ€ Return value πŸŽ€

  1. An rvalue-reference to the current element, or to its copy.
  2. A copy of the underlying iterator. A pointer to the current element is eventually returned if -> is directly used.

πŸ¦‹ Notes πŸ¦‹

Okay so listen up, this part matters πŸ”₯ β€” remember that (2) eventually returns a pointer if -> is directly used. But when you're dereferencing a pointer, the returned value is an lvalue. Which like... lowkey may lead to unintended behavior πŸ™ˆ so watch out bestie.


🌈 Example 🌈

// Run this code

#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

void print(auto rem, auto const& v)
{
    for (std::cout << rem; auto const& e : v)
        std::cout << std::quoted(e) << ' ';
    std::cout << '\n';
}

int main()
{
    std::vector<std::string> p{"alpha", "beta", "gamma", "delta"}, q;
    print("1) p: ", p);
    for (std::move_iterator it{p.begin()}, end{p.end()}; it != end; ++it)
    {
        it->push_back('!'); // calls -> string::push_back(char)
        q.emplace_back(*it); // *it <- overload (1)
    }
    print("2) p: ", p);
    print("3) q: ", q);

    std::vector v{1, 2, 3};
    std::move_iterator it{v.begin()};
    // *it = 13; // error: using rvalue as lvalue
}

(also yes the commented-out line is literally telling you *it = 13; is an error β€” using an rvalue as an lvalue, she said no πŸ’€)


⭐ Possible output ⭐

1) p: "alpha" "beta" "gamma" "delta"
2) p: "" "" "" ""
3) q: "alpha!" "beta!" "gamma!" "delta!"

look at p getting absolutely emptied out and q eating all the leftovers β€” iconic, honestly ate πŸ’…


πŸ’œ Defect reports πŸ’œ

The following behavior-changing defect reports were applied retroactively to previously published C++ standards. (yes, retroactively, she went back in time 🧚)

  • LWG 2106 β€” applied to C++11. Behavior as published: dereferencing a move_iterator could return a dangling reference if the dereferencing the underlying iterator returns a prvalue. Correct behavior: returns the object instead.

(the DR / Applied to / Behavior as published / Correct behavior columns, but make it a bullet list because we're civilized ✨)


🫢 See also 🫢

  • operator[] β€” accesses an element by index (C++11) (public member function)

okay that's the whole page bestie, no cap, every flag and every column accounted for 😭 go forth and move your iterators responsibly πŸ’–

reminder from the fine print: when dereferencing a pointer the returned value is an lvalue, and that may lead to unintended behavior β€” so like, be careful out there πŸ“

✨ that's a wrap ✨ β€” sourced from http://cppreference.com, dated 2024.06.10, on the std::move_i...perator*,->(3) errand. mwah πŸ’‹

πŸ“¦ where this page comes from