0

I have a function that is expected to extract a list of key values from a given string, where each key/value pair is represented by a std::pair, the function has the signature like below:

std::list<std::pair<string, string>> extract(const string &s)

If my implementation looks like:

list<pair<...>> kv_pairs;
for (....) {
  kv_pairs.push_back(make_pair(k, v));
}
return kv_pairs;

1) I don't want any copy to happen and I wonder if RVO/NRVO will be applied for the pairs inside the list and the list holding them.

2) If copy will happen in this case, what could be an alternative data structure implementing this without copying? I can think of a solution using unique_ptr<unorder_map<>>, but in my case, I only need to support iteration of the pairs in the list and don't need to support looking up value by their keys so I would like to avoid unnecessary hash calculation during insertion.

3) I know RVO/NRVO is compiler dependent behavior, is there any approach I can verify if these behavior happens or not easily?

nybon
  • 8,894
  • 9
  • 59
  • 67
  • 3
    Starting from C++17 RVO is mandatory and **not** compiler dependent: https://en.cppreference.com/w/cpp/language/copy_elision Also you can always do old school pass-by-reference. – freakish Jun 03 '20 at 06:52
  • Don't forget movement of the list, which could be done if there's no copy-elision. – Some programmer dude Jun 03 '20 at 06:52
  • ^ That. Since C++11, the list will be move-constructed even without RVO. A move of a list is basically just transferring two pointers (head and tail) and maybe some metadata (size). – cdhowie Jun 03 '20 at 06:53
  • 1
    And as always, always do it the simple and straightforward way first. If there are performance problem in any way, then you measure, benchmark and profile (an optimized build) to find the top two or maybe three bottlenecks and fix those, with plenty of documentation about it (like why you're doing that way instead). – Some programmer dude Jun 03 '20 at 06:54

1 Answers1

1

If you are compiling targeting at least C++11, there are really only two possible outcomes:

  • Without RVO, the returned temporary will be used to move-construct the object to which the return value is assigned. This is basically just shuffling a few pointers around, and will take exactly the same amount of time (which is negligible) no matter how many items are in the list.
  • With RVO, the move-construction is elided.

Both outcomes are very fast and will not involve copying of the list structure.

cdhowie
  • 158,093
  • 24
  • 286
  • 300