C++: Difference between revisions
Line 269: | Line 269: | ||
// do something | // do something | ||
auto end = std::chrono::high_resolution_clock::now(); | auto end = std::chrono::high_resolution_clock::now(); | ||
std::cout << "Time elapsed: " << std:: | std::cout << "Time elapsed: " | ||
<< std::chrono::duration_case<std::chrono::milliseconds>(end - start).count() | |||
<< " ms" << std::endl; | << " ms" << std::endl; | ||
</syntaxhighlight> | </syntaxhighlight> |
Revision as of 15:24, 3 February 2020
C++ is a very popular and powerful language which includes all the low-level features of C (e.g. pointers, operator overloading) along many high-level features (regex, STL containers) thanks to the C++ standard library.
Some people may think of it as an object-oriented version of C.
Usage
How to do things using the C++ standard library (stdlib).
Compilation
g++
g++ my_driver.c [-Iincludefolder] -o my_program.out
Misc optimizations
-std=c++17
for C++17 support-O3
for level 3 optmizations
Syntax
Main
All C++ programs launch in a main
function.
Similar to C, the arguments are int argc
and char *argv[]
.
These can be easily converted to a std::vector<std::string>
for convenience.
#include <string>
#include <vector>
int main(int argc, char *argv[]) {
std::vector<std::string> args(argv, argv + argc);
// Your code here
return EXIT_SUCCESS;
}
Headers
Reference
C++ includes C-headers such as math.h
and cmath
.
The C-style header will place everything in the global namespace while the C++ header will place everything in std
.
You should use cmath
.
Lambda Expressions
Casting
Types of casts C++ has several types of casts. These are the main ones you should use.
static_cast
dynamic_cast
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 reinterpret_cast
.
String
#include <string>
// 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);
String Interpolation
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::string a = "a", b = "b", c = "c";
// apply formatting
std::stringstream s;
s << a << " " << b << " > " << c;
// assign to std::string
std::string str = s.str();
std::cout << str << "\n";
}
Buildings Strings
The Complete Guide to Building Strings In C++
There are multiple ways of buildings strings in C++.
Strings are mutable in C++.
I typically use +
or ostringstream
to build strings.
Filesystem
#include <fstream>
Reading and Writing
Reading and writing is done using fstream
.
If you don't need r/w, use istream
for reading or ostream
for writing.
#include <iostream>
#include <fstream>
int main() {
std::istream my_file("my_file.txt");
std::string line;
# Read line by line
# You can also read using <<
while (getline(my_file, line)) {
std::cout << line << std::endl;
}
return 0;
}
Reading a whole file
Reference and comparison of different methods
#include <fstream>
#include <string>
#include <cerrno>
std::string get_file_contents(std::string filename)
{
std::ifstream in(filename, std::ios::in | std::ios::binary);
if (in)
{
std::string contents;
in.seekg(0, std::ios::end);
contents.resize(in.tellg());
in.seekg(0, std::ios::beg);
in.read(&contents[0], contents.size());
return contents;
}
throw(errno);
}
Regular Expressions
#include <regex>
Reference
Thread
#include <thread>
Sleep
std::this_thread::sleep_for(std::chrono::milliseconds(1));
Parallel For
Memory
#include <memory>
Smart Pointers
Smart Pointers
Smart pointers were added in C++11.
There are 4 types of smart pointers:
auto_ptr
which is deprecatedunique_ptr
shared_ptr
weak_ptr
Use unique_ptr
for ownership models.
Use shared_ptr
when multiple objects need to reference the same thing.
Use weak_ptr
to avoid cyclic dependencies which cause issues with reference counting.
If you are using C++14 or newer, you should use make_unique
or make_shared
which will only make one memory allocation for both the object and the pointer rather than two memory allocations.
Alternatively if you already have a smart pointer, you can call my_ptr.reset(new Car())
to change the pointer or my_ptr.reset()
to deallocate the object referenced by the pointer.
Example:
// 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());
// Or starting from C++14
auto my_car = std::make_unique<Car>();
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
Starting from C++11, you should use smart pointers such as shared_ptr
which have automatic garbage collection.
Traditional C++ does not have garbage collection.
After using new
to allocate an object, use delete
to deallocate it.
You can also use C allocation with malloc
, calloc
, alloca
, and free
, though it is not recommended since these are not type-safe.
Custom Deleter
Custom Deleters
When using smart pointers, the default deleter is the delete
function but you can also specify your own deleter.
# Using a functor
struct AVFrameDeleter {
void operator()(AVFrame *p) { av_frame_free(&p); }
};
std::unique_ptr<AVFrame, AVFrameDeleter> rgb_frame(av_frame_alloc());
# Using free
std::unique_ptr<void *, decltype(std::free) *> my_buffer(std::malloc(10), std::free);
Deallocate
Normally, containers such as std::vector
will automatically deallocate memory from the heap when the destructor is called. However, occationally you may want to coerse this deallocation yourself.
There are a few ways to do this:
- Use smart pointers
- Swap
- Call a clear/shrink/deallocate function
Example Reference:
// Using smart pointers
std::unique_ptr<std::vector<float>> my_vector = make_unique<std::vector<float>>(99);
my_vector.reset();
// Swap
std::vector<float> my_vector(99);
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
// Specific to std::vector
std::vector<float> my_vector(99);
my_vector.clear();
my_vector.shrink_to_fit();
Limits
#include <limits>
Reference
C++ has standard macros such as INT_MAX
.
The limits header adds these limits for every type.
// Equivalent to FLT_MAX
std::numeric_limits<float>::max();
Utility
#include <utility>
std::move
Ref
Use std::move
to move containers.
Algorithm
std::find
Chrono
#include <chrono>
Lots of useful time stuff. Good for timing your code.
auto start = std::chrono::high_resolution_clock::now();
// do something
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Time elapsed: "
<< std::chrono::duration_case<std::chrono::milliseconds>(end - start).count()
<< " ms" << std::endl;
STL
STL is the Standard Template Library.
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.
Many STL containers are now built into the standard library (std) of C++.
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
#include <array>
In C++, you can use std::vector
which gives you a resizable array.
This will allocate an array in the heap.
array vs vector
If you need a statically allocated array, you can use std::array
in the array
header.
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 std::vector
.
If you want to manually allocate an array on the heap, you can do so as follows:
auto my_arr = std::make_shared<std::array<char,64>>();
std::vector
Reference
Use vector for almost everything...
It is an ArrayList.
Note that vector<bool>
is not an array of bools.
This has several nuances so you should use vector<char>
instead.
// 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();
std::deque
Double-ended queue
std::list
Container adaptors
std::queue
std::stack
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();
Associative Containers
Also known as maps or associative arrays.
std::unordered_set
#include <unordered_set>
This is a hashset.
std::unordered_set<int> my_set;
// add things to myset
my_set.insert(5);
// Check contains
my_set.find(5) != my_set.end();
std::unordered_map
- Custom Keys
How to use a rational number as a key in 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) {}
};
Boost
Programming Styles
Modern C++
List of resources
Prefer newer std functions available in C++17.
Use shared pointers instead of new and delete.
- Use clang-format.
Orthodox C++
Reference
Somewhat opposite of modern C++.
Also known as "C with Classes"
Basically only use C++ for its classes. Do everything else C-style.
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 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 exceptions.
- Don't use RTTI.
Useful Libraries
A list of useful libraries
cxxopts
Link
A header-only C++ argument parser.
Note that if you already use Boost, you can use Boost::Program_options
instead.
Eigen
A C++ linear algebra library.