4 ms·
> The biggest one is that copy semantics are default and silent This is not true. The rules are simple: rule of three, rule of five, or the recommended one, ru
by namirez 7y ago
> The biggest one is that copy semantics are default and silent
This is not true. The rules are simple: rule of three, rule of five, or the recommended one, rule of zero [1]. If you define a copy constructor, the compiler won't generate a move constructor. If you define a move constructor explicitly, the compiler won't generate a copy constructor silently. You have total control over how the language behaves.
So in summary, either stick to the rule of 5 or the rule of zero and you won't be surprised. If you don't mind expensive copies, rule of 3 is sufficient.
[1] https://en.cppreference.com/w/cpp/language/rule_of_three https://en.cppreference.com/w/cpp/language/rule_of_three
- jcranmer 7y agoMy point is that doing nothing causes copy semantics to be generated by default. It requires some action (specifying move constructors, for example) to override the silent generation of copy semantics. In other words, if you're not explicitly thinking about whether copy semantics are appropriate (or even legal!), then C++ decides for you that they are. That's not a good default.
- namirez 7y agoAgain not true! If you do nothing, the compiler generates both copy constructors and move constructors. If you pass an xvalue reference, the move is used. If you pass an lvalue reference or a value, the copy is called. The compiler doesn't do anything silently.
- jcranmer 7y agoAgain, you're not understanding, or perhaps, you're assuming that users have a much more thorough understanding of the precise semantics of C++ than they usually do. It generally takes extra effort to force the compiler to use a reference or the move constructor instead of the copy constructor. For example, "for (auto x : container)" will usually involve a copy constructor where a reference might have sufficed. And because copy constructors are generated (unless you take extra effort), there can often be no indication that the most natural form of the construction is actually less efficient than originally desired. Yes, if you're aware of the gotchas, you can avoid them, but it is consistently extra effort that has to be put into doing so, and slipping up and missing the efforts in a few key places means you won't even be alerted that you might have forgotten something.
- namirez 7y agoI understand your point, but the language is evolving to be more powerful and expressive. There were certain rules in the past, and there are some new rules in C++11 and beyond. With regard to your example, that's why you need to use universal references like "for (auto&& x : container)" [1]. It's just a new way of doing things, but it's hardly ambiguous. [1] https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers https://isocpp.org/blog/2012/11/universal-references-in-c11-...