Click here to Skip to main content
15,880,469 members
Articles / Programming Languages / Rust

Rust vs. C++ Comparison

Rate me:
Please Sign up or sign in to vote.
4.43/5 (4 votes)
11 Oct 2018CPOL6 min read 12K   8   1
This article will be useful for people who are familiar with C++ but are new to Rust.

Introduction

The Rust programming language was developed by Mozilla with the aim of creating a better tool for developing their browser Mozilla Firefox. However, the language appeared to be so effective, that many programmers are now opting to use it for software development instead of C++. Rust is syntactically similar to C++, but it provides increased speed and better memory safety.

In order to explain why Rust is a safer and faster language than C++, we decided to create a Rust vs C++ comparison chart that clearly shows the differences between these two languages. This article will be useful for people who are familiar with C++, but are new to Rust.

For better comparison, we’ve chosen features that reveal the key similarities and differences between these two languages.

Zero-cost Abstraction

Issue C++ Rust
Preferring code duplication to abstraction due to high cost of virtual method calls Zero-cost abstraction mechanisms allow you to avoid runtime costs when possible. Zero-cost abstraction mechanisms allow you to avoid runtime costs when possible.

Move Semantics

Issue C++ Rust
Move constructors may leave objects in invalid and unspecified states and cause use-after-move errors Move constructors are suggested to leave the source object in a valid state (yet the object shouldn’t be used in correct programs). A built-in static analyzer disallows use of objects after they have been moved.
Use-after-move errors are detected at runtime using a special sentinel state. The compiler can rely on this built-in analyzer for optimization.
External static code analyzers can spot use-after-move errors at compile time.

Smart Pointers vs. null Pointers

Issue C++ Rust
Use-after-free, double-free bugs, dangling pointers Smart pointers and references are preferred to raw pointers. Smart pointers and references are preferred to raw pointers.
Manual code review can spot use of raw pointers where smart pointers would suffice. Raw pointers can only be used inside unsafe blocks, which can automatically be found by tools.
Null dereferencing errors References are preferred to pointers and cannot be null. References are preferred to pointers and cannot be null.
Null dereferencing is still possible even for smart pointers, but is declared as undefined behavior and should never appear. Null references can be emulated by Option types, which require explicit null checks before use.
Compilers assume that undefined behavior never happens, don’t produce warnings, and use this for optimization (sometimes with fatal consequences for security). Smart pointers return Optional references and therefore require explicit checks as well.
External static code analyzers can spot possible errors at compile time. Raw pointers can be null, but they can only be used inside unsafe blocks. Unsafe blocks need to be carefully reviewed, but they can be found and marked automatically.

Internal Buffer

Issue C++ Rust
Buffer overflow errors Explicitly coded wrapper classes enforce range checks. All slice types enforce runtime range checks.
Debugging builds of the STL can perform range checks in standard containers. Range checks are avoided by most common idioms (e.g. range-based for iterators).

Data Races

Issue C++ Rust
Data races (unsafe concurrent modification of data) Good programming discipline, knowledge, and careful review are required to avoid concurrency errors. The built-in borrow checker and Rust reference model detect and prohibit possible data races at compile time.
External static code analyzers can spot some errors at compile time. A novel locking API makes it impossible to misuse mutexes unsafely (though still allowing incorrectusage).
External code sanitizers can spot some errors at runtime.

Object Initialization

Issue C++ Rust
Uninitialized variables Constructors of user-defined types are recommended to initialize all object fields. All variables must be explicitly initialized before use (checked by the compiler).
Primitive types still have undefined values when not initialized explicitly. All types have defined default values that can be chosen instead of explicit initialization types.
External static code analyzers can spot uninitialized variables.

Static (compile-time) Polymorphism

Issue C++ Rust
Static interfaces for static polymorphism Concepts should provide this feature directly, but they’ve been in development since 2015 and are only scheduled for standardization in C++20. Traits provide a unified way of specifying both static and dynamic interfaces.
Virtual functions and abstract classes may be used to declare interfaces. Static polymorphism is guaranteed to be resolved at compile time.
Virtual function calls may be optimized by particular compilers in known cases.

Adding New Traits

Issue C++ Rust
Extending externally defined classes with new methods Adding new methods normally requires inheritance, which can be inconvenient. Traits can be added to and implemented for any class in any module at a later point.
Unified function call syntax could be used to emulate extension methods (if it gets into C++20). Modules restrict visibility of available methods.

Standard Library

Issue C++ Rust
Legacy design of utility types heavily used by standard library Structured types like std::pair, std::tuple and std::variant can replace ad-hoc structures. Built-in composable structured types: tuples, structures, enumerations.
These types have inconvenient interfaces (though C++17 improves this). Pattern matching allows convenient use of structured types like tuples and enumerations.
Most of the standard library doesn’t use structured types. The standard library fully embraces available pattern matching to provide easy-to-use interfaces.

Branches in Switch Statements

Issue C++ Rust
Forgetting to handle all possible branches in switch statements Code review and external static code analyzers can spot switch statements that don’t cover all possible branches. The compiler checks that match expressions explicitly handle all possible values for an expression.

Typing of Variables

Issue C++ Rust
Complex variable types become tedious to type manually The auto and decltype keywords provide limited type inference (for expressions). Local type inference (for a function body) allows you to explicitly specify types less frequently.
Lambda functions still require manual type specifications, but this is improving with C++17. Function declarations still require explicit types which ensures good readability of code.

Runtime Environment

Issue C++ Rust
Embedded and bare-metal programming have high restrictions on runtime environment The C++ runtime is already fairly minimal, as it directly compiles to machine code and doesn’t use garbage collection. The Rust runtime is already fairly minimal as it directly compiles to machine code and doesn’t use garbage collection.
C++ programs can be built without the standard library with disabled exceptions and dynamic type information, etc. Rust programs can be built without the standard library with disabled range checks, etc.

Using Libraries Written in Other Languages

Issue C++ Rust
Using existing libraries written in C and other languages C libraries are immediately usable by C++ programs. C libraries require Rust-specific header declarations.
Libraries in languages other than C++ require wrappers. Libraries in languages other than Rust require wrappers.
Exporting a C interface requires only a simple extern declaration. Exporting a C interface requires only a simple extern declaration.
There’s no overhead in calling C functions from C++ or calling C++ functions from C. There’s no overhead in calling C functions from Rust or calling Rust functions from C.

Conclusion

In this article, we compared Rust and C++. You have no doubt noticed that both languages use zero-cost abstractions and move semantics. They also both have smart pointers, no garbage collection, and other similarities.

In contrast to C++, Rust has a built-in static analyzer but no uninitialized variables.

Rust avoids possible data races, informs about undefined behavior, and allows null raw pointers inside unsafe blocks. The Rust language also has other distinctive features that allow programmers to achieve better safety and performance of their software. If you’re interested in the basics of Rust, check out our series of in-depth Rust tutorials starting from part 1 here.

Thanks Alexey Lozovsky for contributing to this article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Apriorit Inc.
United States United States
ApriorIT is a software research and development company specializing in cybersecurity and data management technology engineering. We work for a broad range of clients from Fortune 500 technology leaders to small innovative startups building unique solutions.

As Apriorit offers integrated research&development services for the software projects in such areas as endpoint security, network security, data security, embedded Systems, and virtualization, we have strong kernel and driver development skills, huge system programming expertise, and are reals fans of research projects.

Our specialty is reverse engineering, we apply it for security testing and security-related projects.

A separate department of Apriorit works on large-scale business SaaS solutions, handling tasks from business analysis, data architecture design, and web development to performance optimization and DevOps.

Official site: https://www.apriorit.com
Clutch profile: https://clutch.co/profile/apriorit
This is a Organisation

33 members

Comments and Discussions

 
PraiseNice Review Pin
jeffie10011-Oct-18 4:17
jeffie10011-Oct-18 4:17 
I'm noticing more and more about Rust, it seems like a good embedded option to me.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.