
El 12/06/2012 18:18, Dave Abrahams escribió:
Passing by reference always defeats copy elision. Why would you want to do that?
Because the in-out reference (I'm talking about non-const references instead of returning by value) might have enough memory/resources to hold the produced value. An example: 1) s has enough capacity, potentially a single allocation std::string s; s.reserve(largest_path); //one allocation std::string ws; ws.reserve(largest_path); //one allocation for( N times ) { calculate_unix_path(s, directory_name, filename[i]...);//no allocation ws = to_wide_string(s); //no allocation print_s(ws); } 2) s's resources not reused, N*2 allocations std::string s; std::string ws; for( N times ) { //allocation, s's previous memory discarded s = calculate_unix_path(directory_name, filename[i]); //w's previously memory discarded ws = to_wide_string(s); print_s(ws); }
You can catch temporaries by rvalue references to reuse external resources. For generic code, catching by value could do some premature pessimization.
Which pessimization is that?
Example: when copy-construction + swap is more expensive than assignment: template<class T> class any_holder { public: any_holder &operator=(any_holder<T> taken_by_value) { using std::swap; swap(t, taken_by_value); return *this; } private: T t; } typedef any_holder< vector<std::string> > any_complex_t; any_complex_t complex, complex2; modify_complex(complex); modify_complex(complex2); //complex2::t's resources //not reused: taken_by_value //was copy-constructed + swapped //with t instead of copy-assigned complex2 = complex; If any_holder implements copy assignment taking a const reference, t's (vector's) resources are reused.
Passing by value has also another downside: it makes your binary interface dependent on the function implementation (do I copy the parameter?). If I change the implementation I need to break ABI.
I don't see how that follows. Leave the ABI alone. Pass-by-value completely insulates the caller from the callee.
If I modify my implementation because I no longer need the internal copy (e.g. the copy was required by an internal function/helper function), I can't optimize the code and change the signature of the function to take a reference, as name mangling changes and I'll need to recompile the caller. If I offer both lvalue and rvalue reference variants I type a bit more but I can safely change the implementation. This might sound a bit silly, but I don't like the idea of defining an interface because I know what I'll do in the implementation details.
I'm really worried about "pass by value is free" and "return by value is free" statements I'm hearing in some C++11 panels.
Where are you hearing that? I've heard Scott Meyers complain about that too, but as far as I can tell, it's a misunderstanding of what's being said.
Apart from some non-really expert C++11 talks I'm attending I remember this issue in the C&B 2011 Panel with Meyers, Alexadrescu and Sutter, (around minute 41). http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2011-C11-Panel-Scott-...
An example of why, how, and where you want this would be helpful, because I fail to grasp the motivation for something like this. Also, I think you should take it to std-proposals@isocpp.org :-)
Yes, sorry, I think it was a bit off topic. One reason is to have multiple return values without packing them on the callee and unpacking them in the caller. Another reason is to have a single implementation that can reuse resources of possibly constructed N out arguments without the need of a lot of overloads. void produce_abcd ( A &a default{1}, B &b default(2) , C &c default(3), D &d default(4)) { //a, b, c, d might be references //to external objects or references to values //constructed with the "default" construction. // //write code as if a, b, c, d were references //to already existing external objects. //... //If a was externally constructed, resources //are reused. a = ... } //Build four new objects [A a, Bb, C c, D c] -> produce_abcd(a, b, c, d), //build new objects and reuse a&b resources [C c2, D c2] -> produce_abcd(a, b, c2, d2), //build new objects reusing a, b, c, d produce_abcd(a, b, c, d), I'm not sure if benefits outweigh the added complexity and such a proposal would have some difficult areas, specially because I'm don't think there is a way to make current pointer to [member]function implementations compatible with that calling convention (the caller must pass the "state" of the arguments in runtime, as a hidden parameter), or without pessimizing pointer to [member]functions. I don't think I could write such a proposal without help from compiler experts. Regards, Ion