Open shaneasd opened 4 years ago
I think if an object relies on another object when running, and do not want to add the second object as all the needed function's params, than the first object oriented class can only define the second one as:
I think there are specific scenarios to use any of the 1/2/3. Reference has a hiden constraint that the referenced object life should be longer than the holder, and pointer mostly the same, but need not to be initialized at the holder's ctor and can be modified even renewed (but that's rare case); unique_ptr is just like pointer but mostly transfered the onwership if the reference object is from outside; shared_ptr and weak_ptr has other scenarios.
So I think not all the case should not use reference as a member, it has it's own occasion.
I agree, that wording is far too strong and lacks justification. In my opinion, a reference is entirely justified when you want to relay the promise that the external dependency may never be invalid to the code reader/maintainer, to the code user (as they cannot pass nullptr), and perhaps even to the compiler.
the issue with using a reference as a member is that your class becomes non-copyable and non-movable, which isn't an obvious consequence. It may be desirable, but then it's a very subtle way of making a class non-copyable and non-movable.
Using a pointer doesn't have this issue. If one doesn't want the nullptr
state, std::reference_wrapper
could be used instead.
I think it really depends on the use case; in particular, I've only ever used this in situations where the class is in fact non-copyable and non-movable, so this is definitely not "an issue", whereas a pointer actually has the issues I've mentioned above.
the use case here is basically a piece of code that does its job using tools which are provided to it and the tools may not be missing.
I could include
the point is, whoever wrote that original remark has provided a near-universal damnation of a practice and provided no reasoning. I have little doubt that this results in some people changing their code to match the advice, only to introduce the possibility of having to deal with nullptr values when this should not be case, to the exasperation of logic.
I think references are an obvious choice for lock guards and similar types.
With almost all other types I sooner or later encourntered situations where I wanted to be able to default construct the object and/or change what the member points to. Classic example is creating an array/vector and then initialize the elements in a loop. Usually it is possible to transform that somehow in a way that doesn't require this two step initialization (wrap behind a generator iterator or using placement new), but the resulting code tends to become less readable, so that its just not worth it.
Foo a[10];
for( Foo& e : a ) {
e =Foo(...);
}
where this doesn't matter of course is for types that you would create with individual calls to new anyway.
[EDIT: Just to be clear: thats just my personal experience and anyway more about the need for default constructability than ref vs no ref members specifically.]
the issue with using a reference as a member is that your class becomes non-copyable and non-movable,
I don't think that is correct. It makes your class non-copy-assignable, which is different from not being non-copyable. However, it also makes your type essentially non-default constructible (unless you are referring to some global resource of course).
the point is, whoever wrote that original remark has provided a near-universal damnation of a practice and provided no reasoning.
It would be good with justification, of course. However, you're arguing that there are legitimate uses of reference members. The statement said it's "almost always wrong". Both can be true. More justification would be good though.
the point is, whoever wrote that original remark has provided a near-universal damnation of a practice and provided no reasoning.
It would be good with justification, of course. However, you're arguing that there are legitimate uses of reference members. The statement said it's "almost always wrong". Both can be true. More justification would be good though.
I'm arguing that the wording is far too strong and lacks justification of its reasoning. Since I personally know there are legitimate uses of reference members, where they model the relationships in an obvious way, I could therefore, based on my experience, also write a footnote somewhere saying that using pointers (when you can use references) is almost always wrong, and concede that indeed it can be true that there are legitimate uses of pointers... And it would be just as one sided, and... less than useful.
I interpret "almost always wrong" as an indication that something is commonly misused rather than not often useful. You might assert that std::priority_queue is almost always wrong in that considering the complete set of possible problems, it is the correct answer to a very small percentage. However the more useful assertion (and the assertion that I think is the intended reading of "almost always wrong") is whether it is the correct solution in the cases where it seems like it should be.
There are lots of places where I use reference members and it hasn't caused any problem I've noticed. For the assertion that it's "almost always wrong" to be correct given my reading of the phrase then I would have to either have problems in the execution of my code that I haven't noticed or be spending more time or writing more awkward code as a result of my poor design decision.
So either
The question is which is it?
The text "Note that using a reference member is almost always wrong" appears in the exception text for http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#define-copy-move-and-destroy-consistently in appendix C. As far as I can see there is no other treatment of this issue anywhere in the core guidelines. To me this seems like quite a strong (and in my opinion wrong) statement with no justification offered. If it is indeed the opinion put forth by the core guidelines that this is the case then I think it deserves its own rule. If not then I think that comment should be removed or revised.