| ▲ | HarHarVeryFunny a day ago | |||||||
Do you agree that C++ pass-by-value is using copy constructors? Do you agree that the copy constrictors of the C++ standard library (STL) all do deep copy? Do you agree that if you write your own class with a raw pointer member, you would need to write a copy constructor? So, what exactly are you disagreeing about ?! You seem to be saying that if you wrote a C-style structure (no constructors) with a pointer member, then C++ would behave like C, which is true, but irrelevant. We're talking about C++ vs C, but since C++ is a superset of C, then yes you can still screw yourself C-style if you choose to. | ||||||||
| ▲ | Maxatar a day ago | parent [-] | |||||||
>Do you agree that C++ pass-by-value is using copy constructors? C++ is an incredibly complex language that it's almost never the case that you can make a categorical statement this simple and have it be true or false. In C++, pass by value may or may not make use of a copy constructor depending on a set of very complex rules. For example passing an rvalue by value for a class type which defines a move constructor may use the move constructor rather than the copy constructor (emphasis on may because even that isn't guaranteed). Passing an lvalue for a class type may or may not invoke the copy constructor depending on specific language rules regarding copy elision. For fundamental types, there is no copy constructor whatsoever. >Do you agree that the copy constrictors of the C++ standard library (STL) all do deep copy? I absolutely do not agree with this, in fact believing so is absurd and I can't possibly fathom what would lead you to believe this. The principle the C++ standard uses for copying objects is based on Alexander Stepanov's "Elements of Programming" where he defines the concept of a regular type. A regular type does not require making a deep or a shallow copy, what it requires is that copies satisfy the following: The copy must preserve equivalence (if a == b, then copy(a) == copy(b)). The copy must be idempotent in meaning. Copying must not have side effects on the source. So as an example a std::string_view can be copied, but making a copy of it is constant O(1) in both time and space. What is required is that after performing a copy, the original source remains unchanged, operator == returns true between the source and the copy, and that making a copy is an idempotent operation. You can extend this further for other collections as well, a std::vector<Foo*> does not end up making deep copies of the pointers being contained, what it does do is satisfy the conditions for being a regular type. >Do you agree that if you write your own class with a raw pointer member, you would need to write a copy constructor? Absolutely not. Just sticking to the existing standard library types you have things like std::span, all of the iterator types which use pointers under the hood, std::initializer_list, std::string_view was already covered. To be blunt, you're expressing a very superficial understanding of a very complex topic that's part of an even more complex language. In general my advice is... never assume that things in C++ are as simple and straight forward as they appear. If you're using a subset of the language that works for you, great, like really good job and continue doing so and I absolutely don't want to discourage you from using the subet of C++ that works for your use case... but don't then confuse this subset for being representative of either the language as a whole or representative of the vast use cases that C++ belongs to and recognize that the advice you give which works so well for you may actually be really bad advice for someone else working within a different subset of the language. | ||||||||
| ||||||||