Everything is riddled with foot guns and escape hatches but references can't be null.
Everything is riddled with foot guns and escape hatches but references can't be null.
And also - you can get nullable references. The following compiles (and often runs) without a problem:
int functionWithReference(int &ref) {
return ref;
}
int main() {
int* pointer = NULL;
return functionWithReference(*pointer);
}Also the above will not compile. Because compilers can actually detect if you set a pointer to nullptr and then use it. Here, you didn't use it so maybe the compiler won't complain. But in the general case yes it will complain.
You can also get Null references in C# and Java in this same method. You call some unsafe code that directly interacts with memory. That's allowed, and yes it breaks the type invariants.
Point being, if you truly want to argue C++ is weakly-typed then you'd also have to argue C# and Java are weakly-typed. Most people don't do that though, so it's just a matter of bias or familiarity.
I love C++ to death, but calling C++ strongly typed when the only type enforcement that is actually done is either static typing at compile time (which a lot of casts can circumvent) or dynamic_cast at runtime is actually laughable. Like, there are literally 2 casts almost entirely ignore the static type system in reinterpret_cast and const_cast. This isn't even talking about the C style cast that still is possible, which can be any of static_cast, const_cast and reinterpret_cast depending on the context.
C++ will happily run with an invalid type assumption you introduced at compile time, while in both C# and Java you will have a type cast exception. C# and Java do runtime type checks at basically every cast.
Weakness consists of all that the type system doesn't catch.
Like oh, for instance: C++ local variables become pixie dust with terminates. Yet an address of these variables can escape from the scope. The type system does nothing to catch this.
Or: the pointer to a Derived can be converted to a pointer to a Base implicitly. But then pointer arithmetic can be applied. Even if there is an array of Derived there, the displacements are wrong.
Most of the unsafe features from C are present, like argument handling in variadic functions.
Explicit memory management. Code would work with an object may be perfectly well typed as far as the data representation goes except oops something already invoked the delete op on the object.
You can have code that's perfectly fine except oops when exceptions happen.
If C++ were type safe, they wouldn't be all these rules on how to write safe C++. Like do use this kind of smart pointer but don't use this other obsolete one that has issues.
And, to be clear, that behavior ALSO exists in C# and Java. You can absolutely 100% ignore the type system in Java and C# and its supported by the standard. Just like C++.
So if that's your own standard for what is weak, then you must also admit that Java and C# are ALSO weakly typed. But clearly you don't believe that, so you have some sort of logic problem here.
In my opinion, people see C++ differently because C++ code in the wild is fundamentally different. It's high performance and used in domains where that matters, so escape hatches are used more often than other langs.
However IMO the strictness/weakness of a language comes from the language itself. And both C++ and Java/C# provide static checks + runtime type checks with escape hatches.
The difference is that C++ code with raw pointers is (fairly) common.
It compiled for me (after changing NULL to nullptr).
> Because compilers can actually detect if you set a pointer to nullptr and then use it.
Apparently it didn't.
> Here, you didn't use it so maybe the compiler won't complain. But in the general case yes it will complain.
That's incorrect, there's a use of the nullptr.
> You call some unsafe code that directly interacts with memory.
I don't see something explicitly declared as unsafe from the source code alone. It looks like a normal pointer dereference to me.
No, there isn't.
> declared unsafe
Please, I have no patience for the purposefully obtuse. It's clear I was referring to other languages there.
Which, you failed to address. Probably because it was difficult, so you figured if you just said "I'm right" and elaborated nothing nobody would notice. Sorry, that doesn't work on people who are awake.
As I've said, you can argue that C++ is weakly typed but you MUST also address languages like C# and Java to make that argument. You haven't, so nobody will believe you when you say C++ is weakly typed.
fn function_with_reference(reference: &i64) -> i64 {
reference.clone()
}
pub fn main() {
unsafe {
let x = 0 as *mut i64;
function_with_reference(&*x);
}
}
This also compiles, runs, and segfaults. And it doesn't mean that references in Rust can be null - they can't.Your problem is with undefined behaviour or perhaps raw pointers, but not references. The reference itself isn't what's messing this up!
That way of obtaining a null reference is actually quite portable.
Where you going to run aground is when you have some null reference in some scope, and you have some code conditional on it being null. Yet the optimizing compiler assumes that since a reference is being checked for having a null address that comparison is always false.