Always written C++ taking advantage of the language features that allow for safer code and bring it closer to Ada linage than C.
Never saw anyone else doing the same in the enterprise codebases I worked on. My team at CERN was the only exception.
However C++ with teams that haven't drink the safety kool aid, becomes C with a C++ compiler quite fast.
Hence why nowadays I tend to only use it occasionally in side projects.
> So like C++ with unique_ptr, shared_ptr, and RAII?
It is like that, but with stronger guarantees and less overhead.Smart pointers in C++ are very slim, which overhead are you referring to? And which are the stronger guarantees?
Additionally, in C++ there's nothing stopping me from wrapping a unique_ptr around a pointer that's aliased else where. This violates the guarantees of a unique_ptr and forces the user to make sure its invariants are held. In Rust the compiler ensures that your Box (Rust's unique_ptr) can never be owned more than once.
In which case would you like to enforce a thread unsafe version?
>Additionally, in C++ there's nothing stopping me from wrapping a unique_ptr around a pointer that's aliased else where. This violates the guarantees of a unique_ptr and forces the user to make sure its invariants are held. In Rust the compiler ensures that your Box (Rust's unique_ptr) can never be owned more than once.
True, nothing stops you to do that and it is nice to know it on compile time. But I fail to say how you would do this by accident. If you deliberately want to do this kind of things, then you are asking for trouble and it doesn't matter how awesome your language is, you would find a way to shoot your foot.
> In which case would you like to enforce a thread unsafe version?
Any time you don't use shared_ptr in a multithreaded context, you're paying extra for the overhead of atomics. In Rust, if you need shared ownership, but you're not doing anything with threads, you can remove that overhead. If you then later try to use it across threads, the compiler won't let you, until you switch to using Arc.If I am following you well, then what you are saying is that you if you are in a single thread application you don't need to use a shared_ptr equivalent. Wouldn't that mean that you are using a garbage collected pointer? (Which should have a greater overhead than a shared pointer) because otherwise you would be using plain old raw pointers (with all its problems).
> you don't need to use a shared_ptr equivalent
Well, it's the same thing, but without the atmoics. Rc and Arc only differ in the instructions used to update the count, Rc uses regular increment, Arc uses atomic increment. The code is otherwise the same.For stronger guarantees, I was going to point out that if you std::move a uniq_ptr, it becomes null, but Rust prevents using a Box<T> that's been moved at compile time. Your example is good here too.
So you are saying that the lack of move constructors (hence copying the structure) will make Vec<T> faster than std::vector? I don't follow that logic, wouldn't it actually be slower?
> I was going to point out that if you std::move a uniq_ptr, it becomes null
The original becames null because the semantic is actually tranfering ownership which might be desirable depending on the case. Also you need it in case you are using custom deleters.
http://stackoverflow.com/questions/13860219/what-are-the-dif...
> I don't follow that logic,
Specifically, I mean that when the vector changes size, the vector needs to reallocate. In Rust, since there are no move constructors, it's just a memcpy of the whole chunk of memory, one big one. Very straightforward and fast. In C++, you need to call all those move constructors. > The original becames null because the semantic is actually tranfering ownership
Absolutely. In Rust, this is tracked at compile time, and attempting to use after the move is a compile-time error. In C++, you'll get a null pointer dereference. (I _think_ that technically it's in an 'unspecified' state, not a null one, but on my system, null is what I get).> In Rust, since there are no move constructors, it's just a memcpy.
memcpy is actually slower that move the ownership of a buffer, that's why you avoid copying as much as you can (std::vector also uses memcpy inside).
> In Rust, this is tracked at compile time, and attempting to use after the move is a compile-time error.
It is nice to get a misuse at compile time, but my point is that once you transfer the ownership of the pointer you shouldn't be using that unique_ptr anymore. I'm probably biased but I don't see this "accidental" misuse happening often (tbh I haven't seen it ever and I have seen some horrible things in C++ before)
> (std::vector also uses memcpy inside).
I don't think I am communicating myself clearly, so I'll just bow out about this issue, until I have an example ready. I should write one anyway, I just don't have it at the moment. > I'm probably biased but I don't see
this "accidental" misuse happening
> oftenWhile that may be true, as the article points out, all it takes is for someone, anywhere, to slip up once, and then you possibly have a serious security violation. Having the compiler double-check your work is nice.
Wrong. You can write perfectly safe code in C++. You seem to have this ridiculous idea that pointer arithmetic is mandatory on C++. "Pointer arithmetic" is not a feature of C++. It's a feature of how computers work. C++ allows you to do it if you want. Memory pools are not a C++ feature, memory pools are part of how a modern computer and OS works. You know, memory doesn't appear magically in your program.
> Rust forces programmers to indicate ownership and lifetime of memory
So like C++ with unique_ptr, shared_ptr, and RAII?
Also I wanted to say that some of you keep mixing C and C++, calling them "C/C++". They're two different languages.