I think wording like "pass by value" and "pass by reference" obscures the underlying mechanics. The only thing that matters is the argument type, and the typo in question was problematic because it caused an erroneous implicit type conversion where none was intended (copying is, after all, really just a conversion from const T& to T). Rust's ban on implicit conversions thus removes a much larger class of typo-related errors than any particular class can prevent in C++.
It's a tough cookie, IMHO. There are plenty of situations where implicitly converting e.g. const char* to std::string is a boon, but on the other hand, char transparently being accepted as an integer type is seldom the intent.
C++'s heritage is showing. I expect we could have had a smoother ride if C strings didn't exist and std::string was a primitive type instead of a library addition.
It's almost always been the case that C++ has chosen the convenient option instead of the safe option. That's why it's in the position it's in. Rust gets 99% of those same decisions right, and that makes arguably as much difference in code quality as the memory and thread safety that always ends up being the arguing point.
There is a reason why objects in C++ have copy as default. That's because objects in C++ are meant to act as built in types, which by default is copy. Value semantics are important for actually creating correct programs and I would argue references cause more issues in languages than copying does.
Implicit references cause more issues, arguably, yes. I can imagine how passing a dictionary that is then modified by the function internally can be a problem in Java or Python. As long as you're explicit about sharing or borrowing access to data and whether the borrow is mutable, though, I don't think this impacts correctness.
Very true. What people should realize is some languages are designed by some really smart people and I would argue C++ and Rust are those kind of languages. C++ type system uses value semantics which can model mathematical objects really well. Writing code that looks like mathematics is much easier in C++ than say Java or Python because it's type system deals with values. Rust's type system is designed to model resources and is based on linear type theory. Both languages were designed with good theories behind them. Languages like Java and Python on the other hand don't really have a theory behind their type system and it's more adhoc.
You are right, it's affine. I meant to type affine but put linear. You can use #[must_use] to kind of push it towards a linear-like behavior. Thanks Full-Spectral for correcting it.
Both Rust and C++ have value semantics as default. The difference with Rust is that it has value semantics with move as default. C++ type system is based more on pure mathematics as it treats values. Rust's type system is based on a different set of mathematics called linear type theory. So C++ is broadly more useful for mathematical reasoning because objects act as values and are free to be copied everywhere. Rust models resources (not values) and in some ways is more realistic since resources are finite.
But that's my point, the typo in C++ is NOT A BUG, it's how the language and types were designed. In C++ you do more mathematical reasoning while in Rust you do more of a resource reasoning. So in C++ order of operations matters less and in Rust order of operations matters a lot more.
So in C++, natural mathematical expressions and functional programming is a lot easier than in Rust and that has to do with having more mathematical value semantics.
As mentioned above, Rust is based on an affine type system, not linear. On that front, it is primarily different from C++ in that it does move by default instead of copy by default. It's not really any different from C++ wrt to math. And Rust has more functional concepts in it than C++ does, not the other way around.
Unless I'm misunderstanding you, I think you maybe have some misunderstandings of Rust.
This comment is very reasonable and thoughtful but I still don't know how to interpret your top comment.
The two languages under discussion are C++ and Rust, right?
And you said:
"Value semantics are important for actually creating correct programs and I would argue references cause more issues in languages than copying does."
So this would imply that you are saying that Rust makes it harder to create correct problems because of issues caused by references.
I don't think that anybody claimed that C++'s copy semantics are a "bug" in the sense that its inventors did not understand its implications. They might just argue that it is not the right default for a language one would pick for a greenfield project in 2025, for the reasons outlined in the blog.
As a disclaimer, I’m not a fan of several aspects of Rust, but I do think some of its language defaults that are good for performant programs. More importantly, these defaults reduce the mental burden of double checking minor C++ traps, and lets me trust the compiler to do this for me.
Rust makes it harder to create programs based on mathematical reasoning and makes functional programming harder. Rust does make programs managing resources, especially memory, easier.
I personally prefer a language that helps me write mathematical and functional programs. Rust is definitely more efficient by default but not dramatically more efficient compared to C++. I think C++ strikes the right balance here.
Structs and classes are copyable by default in C++ because C structs are always trivially copyable. Making copy constructors opt-in would imply that C++ could not share the struct syntax with C. It's a consequence of backwards compatibility.
imachug@reddit
I think wording like "pass by value" and "pass by reference" obscures the underlying mechanics. The only thing that matters is the argument type, and the typo in question was problematic because it caused an erroneous implicit type conversion where none was intended (copying is, after all, really just a conversion from
const T&
toT
). Rust's ban on implicit conversions thus removes a much larger class of typo-related errors than any particular class can prevent in C++.moreVCAs@reddit
haven’t read the article yet, but most days if you ask me the most annoying thing about c++ i will say implicit type conversions.
wasabichicken@reddit
It's a tough cookie, IMHO. There are plenty of situations where implicitly converting e.g.
const char*
tostd::string
is a boon, but on the other hand,char
transparently being accepted as an integer type is seldom the intent.C++'s heritage is showing. I expect we could have had a smoother ride if C strings didn't exist and
std::string
was a primitive type instead of a library addition.Dean_Roddey@reddit
It's almost always been the case that C++ has chosen the convenient option instead of the safe option. That's why it's in the position it's in. Rust gets 99% of those same decisions right, and that makes arguably as much difference in code quality as the memory and thread safety that always ends up being the arguing point.
EventSevere2034@reddit
There is a reason why objects in C++ have copy as default. That's because objects in C++ are meant to act as built in types, which by default is copy. Value semantics are important for actually creating correct programs and I would argue references cause more issues in languages than copying does.
imachug@reddit
Implicit references cause more issues, arguably, yes. I can imagine how passing a dictionary that is then modified by the function internally can be a problem in Java or Python. As long as you're explicit about sharing or borrowing access to data and whether the borrow is mutable, though, I don't think this impacts correctness.
EventSevere2034@reddit
Very true. What people should realize is some languages are designed by some really smart people and I would argue C++ and Rust are those kind of languages. C++ type system uses value semantics which can model mathematical objects really well. Writing code that looks like mathematics is much easier in C++ than say Java or Python because it's type system deals with values. Rust's type system is designed to model resources and is based on linear type theory. Both languages were designed with good theories behind them. Languages like Java and Python on the other hand don't really have a theory behind their type system and it's more adhoc.
Full-Spectral@reddit
Actually Rust's type system is affine, not linear. So in the middle.
EventSevere2034@reddit
You are right, it's affine. I meant to type affine but put linear. You can use #[must_use] to kind of push it towards a linear-like behavior. Thanks Full-Spectral for correcting it.
Mysterious-Rent7233@reddit
Not in languages that have "reference management" as their key differentiating feature...
EventSevere2034@reddit
Both Rust and C++ have value semantics as default. The difference with Rust is that it has value semantics with move as default. C++ type system is based more on pure mathematics as it treats values. Rust's type system is based on a different set of mathematics called linear type theory. So C++ is broadly more useful for mathematical reasoning because objects act as values and are free to be copied everywhere. Rust models resources (not values) and in some ways is more realistic since resources are finite.
But that's my point, the typo in C++ is NOT A BUG, it's how the language and types were designed. In C++ you do more mathematical reasoning while in Rust you do more of a resource reasoning. So in C++ order of operations matters less and in Rust order of operations matters a lot more.
So in C++, natural mathematical expressions and functional programming is a lot easier than in Rust and that has to do with having more mathematical value semantics.
Full-Spectral@reddit
As mentioned above, Rust is based on an affine type system, not linear. On that front, it is primarily different from C++ in that it does move by default instead of copy by default. It's not really any different from C++ wrt to math. And Rust has more functional concepts in it than C++ does, not the other way around.
Unless I'm misunderstanding you, I think you maybe have some misunderstandings of Rust.
EventSevere2034@reddit
Sorry, you are right, it's affine not linear. I thought affine but typed linear. I corrected my post.
Mysterious-Rent7233@reddit
This comment is very reasonable and thoughtful but I still don't know how to interpret your top comment.
The two languages under discussion are C++ and Rust, right?
And you said:
"Value semantics are important for actually creating correct programs and I would argue references cause more issues in languages than copying does."
So this would imply that you are saying that Rust makes it harder to create correct problems because of issues caused by references.
I don't think that anybody claimed that C++'s copy semantics are a "bug" in the sense that its inventors did not understand its implications. They might just argue that it is not the right default for a language one would pick for a greenfield project in 2025, for the reasons outlined in the blog.
EventSevere2034@reddit
Rust makes it harder to create programs based on mathematical reasoning and makes functional programming harder. Rust does make programs managing resources, especially memory, easier.
I personally prefer a language that helps me write mathematical and functional programs. Rust is definitely more efficient by default but not dramatically more efficient compared to C++. I think C++ strikes the right balance here.
simonask_@reddit
Structs and classes are copyable by default in C++ because C structs are always trivially copyable. Making copy constructors opt-in would imply that C++ could not share the struct syntax with C. It's a consequence of backwards compatibility.