Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any disadvantage of using const reference when iterating over basic types?

I find myself using C++11 more and more lately, and where I would have been using iterators in the past, I now am using range-based for loops whenever possible:

std::vector<int> coll(10); std::generate(coll.begin(), coll.end(), []() { return rand(); } ); 

C++03:

for (std::vector<int>::const_iterator it = coll.begin(); it != coll.end(); ++it) {    foo_func(*it); } 

C++11:

for (auto e : coll) { foo_func(e); } 

But what if the collection element type is a template parameter? foo_func() probably will be overloaded to pass complex (= expensive to copy) types by const reference, and simple ones by value:

foo_func(const BigType& e) { ... }; foo_func(int e) { ... }; 

I didn't give this much thought while I was using the the C++03-style code above. I would iterate the same way, and since dereferencing a const_iterator produces a const reference, everything was fine. But using the C++11 range-based for loop, I need to use a const reference loop variable to obtain the same behavior:

for (const auto& e : coll) { foo_func(e); } 

And suddenly I wasn't sure anymore, if this wouldn't introduce unnecessary assembly instructions if auto was a simple type (such as a behind-the-scene pointer to implement the reference).

But compiling a sample application confirmed that there is no overhead for simple types, and that this seems to be the generic way to use range-based for loops in templates. If this hadn't been the case, boost::call_traits::param_type would have been the way to go.

Question: Are there any guarantees in the standard?

(I realize that the issue is not really related to range-based for loops. It's also present when using const_iterators.)

like image 674
Daniel Gehriger Avatar asked Oct 24 '12 20:10

Daniel Gehriger


People also ask

When should we use a const reference and why?

When we create our own copy constructor, we pass an object by reference and we generally pass it as a const reference. One reason for passing const reference is, we should use const in C++ wherever possible so that objects are not accidentally modified.

Can a const reference change?

But const (int&) is a reference int& that is const , meaning that the reference itself cannot be modified.

When should const be used C++?

The const keyword allows you to specify whether or not a variable is modifiable. You can use const to prevent modifications to variables and const pointers and const references prevent changing the data pointed to (or referenced).

What is the point of a const reference?

- const references allow you to specify that the data referred to won't be changed. A const reference is actually a reference to const. A reference is inherently const, so when we say const reference, it is not a reference that can not be changed, rather it's a reference to const.


1 Answers

The standard containers all return references from their iterator (note, however, that some "containers aren't really container, e.g., std::vector<bool> which returns a proxy). Other iterators might return proxies or values although this isn't strictly supported.

Of course, the standard doesn't make any guarantees with respect to performance. Any sort of performance related feature (beyond complexity guarantees) are considered to be quality of implementation.

That said, you might want to consider having the compiler make the choice for you as it did before:

for (auto&& e: coll) { f(e); } 

The main issue here is that f() may receive a non-const reference. This can be prevented if necessary using a const version of coll.

like image 200
Dietmar Kühl Avatar answered Sep 20 '22 08:09

Dietmar Kühl