5,321
edits
No edit summary |
|||
(42 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
__FORCETOC__ | __FORCETOC__ | ||
C++ is a very popular and powerful language which includes all the low-level features of [[C_(programming_language) | C]] (e.g. pointers, operator overloading) along many high-level features (regex, STL containers) thanks to the C++ standard library.<br> | |||
Some people may think of it as an object-oriented version of C. | |||
==Usage== | ==Usage== | ||
Line 14: | Line 16: | ||
===Syntax=== | ===Syntax=== | ||
====Main==== | |||
All C++ programs launch in a <code>main</code> function. | |||
Similar to [[C]], the arguments are <code>int argc</code> and <code>char *argv[]</code>. | |||
These can be easily converted to a <code>std::vector<std::string></code> for convenience. | |||
<syntaxhighlight lang="cpp"> | |||
#include <string> | |||
#include <vector> | |||
int main(int argc, char *argv[]) { | |||
std::vector<std::string> args(argv, argv + argc); | |||
// Your code here | |||
return EXIT_SUCCESS; | |||
} | |||
</syntaxhighlight> | |||
====Headers==== | |||
[https://stackoverflow.com/questions/10694255/cmath-vs-math-h-and-similar-c-prefixed-vs-h-extension-headers Reference] | |||
C++ includes C-headers such as <code>math.h</code> and <code>cmath</code>.<br> | |||
The C-style header will place everything in the global namespace while the C++ header will place everything in <code>std</code>.<br> | |||
You should use <code>cmath</code>. | |||
====Lambda Expressions==== | ====Lambda Expressions==== | ||
[https://en.cppreference.com/w/cpp/language/lambda Reference] | [https://en.cppreference.com/w/cpp/language/lambda Reference] | ||
=== | ====Casting==== | ||
[https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used Types of casts] | |||
C++ has several types of casts. | |||
These are the main ones you should use. | |||
* <code>static_cast</code> | |||
* <code>dynamic_cast</code> | |||
If you're casting between things but do not want to change the bit-pattern (e.g. binary data or pointers), you can also use <code>reinterpret_cast</code>. | |||
===String=== | |||
<code>#include <string></code><br> | |||
<syntaxhighlight lang="cpp"> | |||
// c-str to string | |||
char *old_string = "my c-style string"; | |||
string cpp_string(old_string); | |||
// string to c-str | |||
cpp_string.c_str(); | |||
// char to string | |||
char my_char = 'a'; | |||
string my_str(1, my_char); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
====String Interpolation==== | ====String Interpolation==== | ||
[https://stackoverflow.com/questions/10410023/string-format-alternative-in-c Reference] | [https://stackoverflow.com/questions/10410023/string-format-alternative-in-c Reference] | ||
Line 46: | Line 81: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
====Buildings Strings==== | |||
[https://www.fluentcpp.com/2017/12/19/build-strings-from-plain-string-up-to-boost-karma/ The Complete Guide to Building Strings In C++]<br> | |||
There are multiple ways of buildings strings in C++.<br> | |||
Strings are mutable in C++.<br> | |||
I typically use <code>+</code> or <code>ostringstream</code> to build strings. | |||
===Filesystem=== | ===Filesystem=== | ||
<code>#include <fstream></code><br> | |||
====Reading and Writing==== | ====Reading and Writing==== | ||
Reading and writing is done using <code>fstream</code>.<br> | Reading and writing is done using <code>fstream</code>.<br> | ||
Line 73: | Line 116: | ||
#include <cerrno> | #include <cerrno> | ||
std::string get_file_contents( | std::string get_file_contents(std::string filename) | ||
{ | { | ||
std::ifstream in(filename, std::ios::in | std::ios::binary); | std::ifstream in(filename, std::ios::in | std::ios::binary); | ||
Line 83: | Line 126: | ||
in.seekg(0, std::ios::beg); | in.seekg(0, std::ios::beg); | ||
in.read(&contents[0], contents.size()); | in.read(&contents[0], contents.size()); | ||
return contents; | |||
return | |||
} | } | ||
throw(errno); | throw(errno); | ||
Line 91: | Line 133: | ||
===Regular Expressions=== | ===Regular Expressions=== | ||
<code>#include <regex></code><br> | |||
[https://en.cppreference.com/w/cpp/regex Reference] | [https://en.cppreference.com/w/cpp/regex Reference] | ||
<!-- | <!-- | ||
Line 105: | Line 148: | ||
===Thread=== | ===Thread=== | ||
<code>#include <thread></code><br> | |||
==== Sleep ==== | ==== Sleep ==== | ||
<syntaxhighlight lang="C++"> | <syntaxhighlight lang="C++"> | ||
Line 113: | Line 157: | ||
===Memory=== | ===Memory=== | ||
<code>#include <memory></code><br> | |||
====Smart Pointers==== | ====Smart Pointers==== | ||
[https://www.geeksforgeeks.org/auto_ptr-unique_ptr-shared_ptr-weak_ptr-2/ Smart Pointers]<br> | [https://www.geeksforgeeks.org/auto_ptr-unique_ptr-shared_ptr-weak_ptr-2/ Smart Pointers]<br> | ||
Line 124: | Line 169: | ||
Use <code>shared_ptr</code> when multiple objects need to reference the same thing.<br> | Use <code>shared_ptr</code> when multiple objects need to reference the same thing.<br> | ||
Use <code>weak_ptr</code> to avoid cyclic dependencies which cause issues with reference counting.<br> | Use <code>weak_ptr</code> to avoid cyclic dependencies which cause issues with reference counting.<br> | ||
If you are using C++14 or newer, you should use <code>make_unique</code> or <code>make_shared</code> which will only make one memory allocation for both the object and the pointer rather than two memory allocations.<br> | |||
Alternatively if you already have a smart pointer, you can call <code>my_ptr.reset(new Car())</code> to change the pointer or <code>my_ptr.reset()</code> to deallocate the object referenced by the pointer. | |||
Example: | Example: | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
// Block-scope car | |||
Car my_car; | |||
// Old C++ | |||
// Must call delete my_car; to avoid memory leaks. | |||
Car *my_car = new Car(); | |||
// Using unique ptr | |||
std::unique_ptr<Car> my_car(new Car()); | std::unique_ptr<Car> my_car(new Car()); | ||
// Or starting from C++14 | // Or starting from C++14 | ||
auto my_car = std::make_unique<Car>(); | auto my_car = std::make_unique<Car>(); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Note: If the object you need is not very large, you can consider just including it as part of your class (or leaving it on the stack) rather than use pointers. | |||
====Garbage Collection==== | ====Garbage Collection==== | ||
Line 159: | Line 216: | ||
There are a few ways to do this: | There are a few ways to do this: | ||
* Use smart pointers | * Use smart pointers | ||
* | * Swap | ||
* Call a clear/shrink/deallocate function | * Call a clear/shrink/deallocate function | ||
Example [https://stackoverflow.com/questions/3054567/right-way-to-deallocate-an-stdvector-object Reference]: | Example [https://stackoverflow.com/questions/3054567/right-way-to-deallocate-an-stdvector-object Reference]: | ||
Line 167: | Line 224: | ||
my_vector.reset(); | my_vector.reset(); | ||
// | // Swap | ||
std::vector<float> my_vector(99); | std::vector<float> my_vector(99); | ||
std::vector< | my_vector = std::vector<float>; | ||
// Or alternatively | |||
// std::vector<float>().swap(my_vector); | |||
// Swap for cl::Buffer | |||
cl::Buffer my_buf(context, CL_MEM_READ_WRITE, size); | |||
my_buf = cl::Buffer(); | |||
// Clear and shrink | // Clear and shrink | ||
Line 179: | Line 242: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== | ===Limits=== | ||
[https:// | <code>#include <limits></code><br> | ||
C++ has | [https://en.cppreference.com/w/cpp/types/numeric_limits Reference]<br> | ||
C++ has standard macros such as <code>INT_MAX</code>.<br> | |||
The limits header adds these limits for every type.<br> | |||
<syntaxhighlight lang="cpp"> | |||
If you | // Equivalent to FLT_MAX | ||
std::numeric_limits<float>::max(); | |||
</syntaxhighlight> | |||
===Utility=== | |||
<code>#include <utility></code><br> | |||
====std::move==== | |||
[https://en.cppreference.com/w/cpp/utility/move Ref]<br> | |||
Use <code>std::move</code> to move containers. | |||
===Algorithm=== | |||
====std::find==== | |||
[https://en.cppreference.com/w/cpp/algorithm/find Reference]<br> | |||
==STL== | |||
STL is the Standard Template Library.<br> | |||
STL can either refer to the 1994 original STL implementation by Stepanov and Lee from HP or the general set of algorithms, containers, functions, and iterators.<br> | |||
Many STL containers are now built into the standard library (std) of C++.<br> | |||
This section focuses only on the portions of STL which have been incorporated into the C++ standard library. | |||
===Simple Containers=== | |||
====std::pair==== | |||
===Sequences=== | |||
====std::array==== | |||
<code>#include <array></code><br> | |||
In C++, you can use <code>std::vector</code> which gives you a resizable array. | |||
This will allocate an array in the heap.<br> | |||
[https://shendrick.net/Coding%20Tips/2015/03/15/cpparrayvsvector.html array vs vector]<br> | |||
If you need a static sized array, you can use <code>std::array</code> in the <code>array</code> header.<br> | |||
This wrapper around C-style arrays gives us size information and allows the array to be passed around by reference while keeping the array on the stack unlike <code>std::vector</code>.<br> | |||
If you want to allocate a static array on the heap, you can do so as follows: | |||
<syntaxhighlight lang="C++"> | |||
auto my_arr = std::make_shared<std::array<char,64>>(); | |||
</syntaxhighlight> | |||
====std::vector==== | |||
[https://en.cppreference.com/w/cpp/container/vector Reference]<br> | |||
Use vector for almost everything...<br> | |||
It is an ArrayList.<br> | |||
Note that <code>vector<bool></code> is not an array of bools.<br> | |||
This has several nuances so you should use <code>vector<char></code> instead.<br> | |||
<syntaxhighlight lang="c++"> | |||
// Basics | |||
vector my_vec; | |||
// Vector with size 5 | |||
vector my_vec(5); | |||
// Vector with size 5 initialized to 1 | |||
vector my_vec(5, 1); | |||
// Length of vector | |||
my_vec.size(); | |||
// Equivalent to size()==0 | |||
my_vec.empty(); | |||
// Equivalent to my_vec[0]; | |||
// Undefined on empty vectors | |||
my_vec.front(); | |||
// Equivalent to my_vec[my_vec.size()-1]; | |||
// Undefined on empty vectors | |||
my_vec.back(); | |||
</syntaxhighlight> | |||
====std::deque==== | |||
Double-ended queue | |||
====std::list==== | |||
===Container adaptors=== | |||
====std::queue==== | |||
[https://en.cppreference.com/w/cpp/container/queue Reference]<br> | |||
<syntaxhighlight lang="c++"> | |||
</syntaxhighlight> | |||
====std::stack==== | |||
[https://en.cppreference.com/w/cpp/container/stack cppreference] | |||
<syntaxhighlight lang="cpp"> | |||
std::stack<char> my_stack; | |||
// Push to stack | |||
// You can also use emplace | |||
// Returns void | |||
my_stack.push('a'); | |||
// Peek | |||
// Always make sure stack is not empty | |||
char top = my_stack.top('a'); | |||
// Pop | |||
// Note: returns void | |||
// Always make sure stack is not empty | |||
my_stack.pop(); | |||
</syntaxhighlight> | |||
===Associative Containers=== | |||
Also known as maps or associative arrays. | |||
====std::unordered_set==== | |||
<code>#include <unordered_set></code><br> | |||
This is a hashset.<br> | |||
<syntaxhighlight lang="cpp> | |||
std::unordered_set<int> my_set; | |||
// add things to myset | |||
my_set.insert(5); | |||
// Check contains | |||
my_set.find(5) != my_set.end(); | |||
</syntaxhighlight> | |||
====std::unordered_map==== | |||
;Custom Keys | |||
How to use a rational number as a key in C++ | |||
<syntaxhighlight lang="C++"> | |||
struct Fraction | |||
{ | |||
int num; | |||
int den; | |||
bool operator==(const Fraction &other) const { | |||
return num*other.den == den * other.num; | |||
} | |||
Fraction(int a, int b) : num(a), den(b) {} | |||
}; | |||
</syntaxhighlight> | |||
==Boost== | |||
==Programming Styles== | ==Programming Styles== | ||
Line 196: | Line 388: | ||
[https://gist.github.com/bkaradzic/2e39896bc7d8c34e042b Reference]<br> | [https://gist.github.com/bkaradzic/2e39896bc7d8c34e042b Reference]<br> | ||
Somewhat opposite of modern C++.<br> | Somewhat opposite of modern C++.<br> | ||
Basically only use C++ for its classes. Do everything else C-style. | Also known as "C with Classes"<br> | ||
Basically only use C++ for its classes. Do everything else C-style.<br> | |||
The main benefit is compatibility with older compilers/libraries and easier understanding for people less familiar with newer C++ features. | The main benefit is compatibility with older compilers/libraries and easier understanding for people less familiar with newer C++ features. | ||
*Don't use C++ runtime wrapper for C runtime includes (<cstdio>, <cmath>, etc.), use C runtime instead (<stdio.h>, <math.h>, etc.) | * Don't use C++ runtime wrapper for C runtime includes (<cstdio>, <cmath>, etc.), use C runtime instead (<stdio.h>, <math.h>, etc.) | ||
*Don't use stream (<iostream>, <stringstream>, etc.), use printf style functions instead. | * Don't use stream (<iostream>, <stringstream>, etc.), use printf style functions instead. | ||
*Don't use anything from STL that allocates memory, unless you don't care about memory management. | * Don't use anything from STL that allocates memory, unless you don't care about memory management. | ||
* Don't use exceptions. | |||
* Don't use RTTI. | |||
==Boost== | ==Useful Libraries== | ||
== | A list of useful libraries | ||
===cxxopts=== | |||
[https://github.com/jarro2783/cxxopts Link]<br> | |||
A header-only C++ argument parser.<br> | |||
Note that if you already use Boost, you can use <code>Boost::Program_options</code> instead. | |||
===Eigen=== | |||
{{main | Eigen (C++ library)}} | |||
A C++ linear algebra library. |