Avoid temporary copies in C++11 ranged-based for loops. #12169

pull ghost wants to merge 1 commits into bitcoin:master from changing 8 files +19 −19
  1. ghost commented at 11:23 am on January 12, 2018: none

    The ::value_type of the std::map/std::unordered_map containers is std::pair<const Key, T>.

    Currently a lot of loops drop the const from the iterator which forces the compiler to create a copy, this should be avoided by using the auto keyword.

    A better explanation can be found in Meyer’s Effective Modern C++.

    https://books.google.de/books?id=rjhIBQAAQBAJ&lpg=PA41&ots=FmZL15vynY&pg=PA41#v=onepage&q&f=false

  2. fanquake added the label Refactoring on Jan 12, 2018
  3. laanwj commented at 10:00 am on February 12, 2018: member

    Currently a lot of loops drop the const from the iterator which forces the compiler to create a copy, this should be avoided by using the auto keyword.

    I don’t understand this rationale for using auto. Why doesn’t adding const to the iterator have the same effect of avoiding copies?

  4. ryanofsky commented at 12:00 pm on February 12, 2018: member

    I don’t understand this rationale for using auto. Why doesn’t adding const to the iterator have the same effect of avoiding copies?

    If you take a const reference to a type that requires an implicit conversion it will make a copy. Example where loop items are copied:

    0vector<pair<int, int>> v;
    1...
    2for (const pair<short, short>& p : v);
    

    Using auto would avoid the copy. You could also drop const to trigger a compiler error if the copies are unintended.

  5. dcousens commented at 12:03 pm on February 12, 2018: contributor
     0#include <iostream>
     1
     2struct Foo {
     3	Foo () { std::cout << "  Foo()" << std::endl; }
     4	Foo (const Foo& z) { std::cout << "  Foo(Foo)" << std::endl; }
     5	Foo (const Foo&& z) { std::cout << "  Foo(Foo&&)" << std::endl; }
     6};
     7using FooInt = std::pair<const Foo, int>;
     8
     9int main () {
    10	std::cout << "Init" << std::endl;
    11	const auto bar = {
    12		FooInt{ Foo(), 0 },
    13		{ Foo(), 1 },
    14		{ Foo(), 2 }
    15	};
    16
    17	std::cout << "FooInt : bar" << std::endl;
    18	for (FooInt x : bar) {}
    19
    20	std::cout << "const FooInt& : bar" << std::endl;
    21	for (const FooInt& x : bar) {}
    22
    23	std::cout << "const std::pair<Foo, int>& : bar" << std::endl;
    24	for (const std::pair<Foo, int>& x : bar) {}
    25
    26	std::cout << "const std::pair<const Foo, int>& : bar" << std::endl;
    27	for (const std::pair<const Foo, int>& x : bar) {}
    28
    29	std::cout << "auto : bar" << std::endl;
    30	for (auto x : bar) {}
    31
    32	std::cout << "auto& : bar" << std::endl;
    33	for (auto& x : bar) {}
    34
    35	std::cout << "const auto& : bar" << std::endl;
    36	for (const auto& x : bar) {}
    37
    38	return 0;
    39}
    
     0$ g++ foo.cpp && ./a.out
     1<snip>
     2FooInt : bar
     3  Foo(Foo)
     4  Foo(Foo)
     5  Foo(Foo)
     6const FooInt& : bar
     7const std::pair<Foo, int>& : bar
     8  Foo(Foo)
     9  Foo(Foo)
    10  Foo(Foo)
    11const std::pair<const Foo, int>& : bar
    12auto : bar
    13  Foo(Foo)
    14  Foo(Foo)
    15  Foo(Foo)
    16auto& : bar
    17const auto& : bar
    

    Why doesn’t adding const to the iterator have the same effect of avoiding copies?

    tl;dr it does have the same effect. AFAIK. Although personally I think auto helps prevent these nits, you weren’t wrong in your assumption.

    edit: wait, if you meant const on the std::pair, not the Key, see above.

  6. MarcoFalke commented at 10:42 pm on February 12, 2018: member
    Needs rebase if still relevant
  7. Avoid temporary copies in C++11 ranged-based for loops.
    The ::value_type of the std::map/std::unordered_map containers is
    std::pair<const Key, T>.
    
    Currently a lot of loops drop the const from the iterator which forces
    the compiler to create a copy, this should be avoided by using the auto
    keyword.
    
    A better explanation can be found in Meyer's Effective Modern C++.
    
    https://books.google.de/books?id=rjhIBQAAQBAJ&lpg=PA41&ots=FmZL15vynY&pg=PA41#v=onepage&q&f=false
    53b26f5632
  8. ghost commented at 8:02 pm on February 13, 2018: none
    rebased
  9. jnewbery commented at 6:11 pm on April 4, 2018: member
    needs rebase
  10. Empact commented at 12:15 pm on April 18, 2018: member
    Would be great to avoid these copies, but IMO there is potential documentation / clarity benefit to being explicit about the pair types. How about changing this to just add const to the key types?
  11. MarcoFalke added the label Up for grabs on Apr 19, 2018
  12. laanwj commented at 12:33 pm on April 26, 2018: member
    Going to close this as it seems to be inactive, let me know if you want to pick it up again then I’ll reopen.
  13. laanwj closed this on Apr 26, 2018

  14. Empact commented at 9:34 pm on May 14, 2018: member
    I’ll take it.
  15. fanquake removed the label Up for grabs on May 17, 2018
  16. laanwj referenced this in commit 31145a3d7c on Jun 24, 2018
  17. PastaPastaPasta referenced this in commit 60e0ee4a99 on Jul 7, 2020
  18. PastaPastaPasta referenced this in commit 85f633e26b on Jul 7, 2020
  19. PastaPastaPasta referenced this in commit c298c1ef77 on Jul 8, 2020
  20. DrahtBot locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-10-04 22:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me