C++ Language

Install

# MacOS
xcode-select --install

Hello World

#include <iostream>
int main()
{
    std::cout << "Hello world!" << std::endl;
    return 0;
}

编译与运行

g++ main.cpp -o main.out
./main.out

输入输出

iosteam

#include <iostream>
int main()
{
    int v1 = 0, v2 = 0;
    std::cin >> v1 >> v2;
    std::cout << "The sum of " << v1 << " and " << v2 << " is " << v1+v2 << std::endl;
    return 0;
}

不知道有多少个输入时

int main()
{
    string word;
    while (cin >> word)
        cout << word << endl;
    return 0;
}

读取整行

int main()
{
    string line;
    while (getline(cin, line))
        cout << line << endl;
    return 0;
}

fstream

#include <fstream>

// open file
ofstream outfile("file.txt");

// append file
ofstream outfile("file.txt", ios_base::app);

// write data to file
if (! outfile)
    cerr << "failed to open file.\n";
else
    outfile << "content" << endl;

// read data from file
ifstream infile("file.txt");
if (! infile)
    cerr << "failed to open file.\n";
else {
    while (infile >> word) {
        cout << word << endl;
    }
}

注释

/*
 * multi-line
 * comment
 */
int main()
{
    // single line comment
    return 0;
}

流程控制

while

#include <iostream>
int main()
{
    int i = 0;
    while (i < 10) {
        std::cout << i << std::endl;
        ++i;
    }
}

for

#include <iostream>
int main()
{
    for (int i = 0; i < 10; ++i) {
        std::cout << i << std::endl;
    }
}

if

#include <iostream>
int main()
{
    int i = 0, j = 1;
    std::cin << i;
    if (i > j) {
        std::cout << "i > j" << std::endl;
    } else if (i < j) {
        std::cout << "i < j" << std::endl;
    } else {
        std::cout << "i = j" << std::endl;
    }
}

switch

char ch;
int aCnt = 0, bCnt = 0, cCnt = 0;
std::cin >> ch;
switch (ch) {
    case 'a':
        ++aCnt;
        break;
    case 'b':
        ++bCnt;
        break;
    case 'c':
        ++cCnt;
        break;
}

Null statement

;
{}

类型

基础类型

Type Meaning Minumum Size
bool boolean NA
char character 8 bits
wchar_t wide character 16 bits
char16_t Unicode character 16 bits
char32_t Unicode character 32 bits
short short integer 16 bits
integer integer 16 bits
long long integer 32 bits
long long long integer 64 bits
float single-precision floating-point 6 significant digits
double double-precision floating-point 10 significant digits
long double extended-precision floating-point 10 significant digits
  • signed short: [-32768, 32767]
  • unsigned short: [0, 65535]
  • signed int: [-2^15, 2^15-1]
  • unsigned int: [0, 2^16-1]

Conversion

int i = 3.14;
bool b = i;
signed char = 256; // undefined

Literals

int i = 20;  // demical
int i = 024; // octal
int i = 0x14; // hexadecimal
long i = 1024L; // long
long long i = 1024LL; long long
unsigned int i = 20u; unsigned
float f = 3.14;
float f = 3.14E0;
long double f = 3.14L; // long double
char c = 'a'; // character literal
char16_t c = u'a'; // Unicode 16 character literal
char32_t c = U'a'; // Unicode 32 character literal
string s = "Hello"; // string literal
string s = "Hello "
           "world!"; // multiline string literal
string s = u8"Hello"; // utf-8 string literal

类型别名

typedef double wages;  // wages is a synonym for double
using SI = Sales_item; // SI is a synonym for Sales_item

类型推断

auto i = 0, *p = &i;    // 自动推断类型

decltype(f()) sum = x;  // 获取表达式的类型

指针、引用、常量

  • int &r: &在declaration中,表示reference
  • int *p: *在declaration中,表示pointer
  • &i: &在expression中,表示address-of operator
  • *p: *在expression中,表示dereference operator
int x = 1024;
int &ref = x;              // ref是x的引用,引用不可被修改(rebind),必需初始化
int * p1 = &x;             // 指针可以被修改,值也可以被修改
const int * p2 = &x;       // 指针可以被修改,值不可以被修改(const int)
int * const p3 = &x;       // 指针不可以被修改(* const),值可以被修改
const int * const p4 = &x; // 指针不可以被修改,值也不可以被修改

void *p = &obj;            // 可以指向任意类型对象的地址
int *p = nullptr;          // 空指针
int **pp = &p;             // 指向指针的指针
int *&ref = p;             // 指针的引用
  • top-level const: a pointer itself is a const
  • low-level const: a pointer points to a const

指针函数与函数指针

// addition是指针函数,一个返回类型是指针的函数
int* addition(int a, int b) {
    int* sum = new int(a + b);
    return sum;
}

int subtraction(int a, int b) {
    return a - b;
}

int operation(int x, int y, int (*func)(int, int)) {
    return (*func)(x,y);
}

// minus是函数指针,指向函数的指针
int (*minus)(int, int) = subtraction;
int* m = addition(1, 2);
int n = operation(3, *m, minus);

Operators

Operators Category Operators Operand Result
Arithmetic +,-,*,/,% rvalue rvalue
Logical and Relational !,<,<=,>,>=,==,!=,&&,` `
Assignment = left-hand operand must be a modifiable lvalue left-hand operand lvalue
Increment/Decrement ++,-- lvalue prefix: changed lvalue; postfix: unchanged lvalue
Member Access . lvalue or rvalue lvalue if the operand is lvalue
Member Access -> pointer lvalue
Conditional cond ? expr1 : expr2 lvalue if both expr are lvalues
Bitwise ~,<<,>>,&,^,` `
sizeof size_t
Comma , right-hand expression, left-hand expression discard

lvalue and rvalue

  • lvalue: the object’s identity (its location in memory)
  • rvalue: the object’s value (its contencts)

Function

should be declared in header, defined in source file, and the source file should include the header.

// void return
void func() {
    return;
}

// return value
int func() { return 1; }

// return vector
vector<string> func() { return {"a", "b", "c"};}

// pass by value
// 调用时复制值
void func(int x, int y){;}

// pass by reference
// 用于修改对象
void func(int &i) {
    i = 0; // change the value of the object
}

// const reference
// 函数中用到但是不修改的对象
void func(const string &s){;}

// local static object
void func() {
    static int cnt=0;   // value will persist across calls
}

// 不定长参数
#include <initializer_list>
void error_msg(initializer_list<string> il){
    for (auto beg = il.begin(); beg != il.end(); ++beg)
        cout << *beg << " ";
    cout << endl;
}

// declaration
void print(vector<int>::const_iterator beg, vector<int>::const_iterator end);
bool lengthCompare(const string &, const string &); // parameter names not required but nice to have

Pointer of function

// definition
bool (*pf)(const string &, const string &); // pf is a pointer to function whose return is bool and parameter list is const string and const string

// assignment
pf = lengthCompare; // points to the function
pf = &lengthCompare; // equivalent to above

// call
pf("hello", "world"); // call the function
(*pf)("hello", "world"); // equivalent call

Lambda expression

[capture list](parameter list) -> return type {function body}

  • [=]: implicit by value capture list
  • [&]: implicit by reference capture list
auto f = [] { return 42; }; // empty parameter list
[](const string &a, const string &b) { return a.size < b.size; }; // with parameters
[sz](const string &a) { return a.size() > sz; }; // with capture list 
[=](const string &a) { return a.size() > sz; }; // auto infer capture list
[](int i) -> int {if (i<0) return -i; else return i;}; // specify return type

Binding arguments

#include <functional>
auto newCallable = bind(callable, arg_list);

// example
using namespace std::placeholders;
auto check6 = bind(check_size, _1, 6); // binding other arguments except the first argument, 6 is the binded argument

// f has 5 arguments, g has 2, the first, second arguments of g is the last, the 3rd of f
auto g = bind(f, a, b, _2, c, _1);

Struct

struct Sales_data {
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};
// semicolon is needed at the end

Sequential Containers

Generic

Iterator

string s = "hello";

// using `for` for iteratrion
for (auto it = s.begin(); it != s.end(); ++it)
    *it = toupper(*it);

// using `while` for iteratrion
auto it = s.begin();
while (it != s.end()){
    *it = toupper(*it);
    ++it;
}

// iterator type
string s;
string::iterator it = s.begin();
vector<int> ivec;
vector<int>::iterator it = ivec.begin();

// const iterator, read but do not write to an object
vector<int> ivec;
auto it1 = ivec.cbegin(), it2 = ivec.cend();

// member access
(*it).empty();
it->empty();

// arithmetic operations
auto mid = vec.begin() + vec.size() / 2;
// or
auto beg = vec.begin(), end = vec.end();
auto mid = beg + (end - beg) / 2;

assign

vector<int> ivec1={1,2,3}, ivec2={};
ivec2.assign(ivec1);
ivec2.assign(ivec1.begin(), ivec1.end());
ivec2.assign(1, 3); // {1,1,1}

swap

swap(ivec1, ivec2);

accessing

// access return references
c.back(); // return last element
c.front(); // return first element
c[n]; // return the n-th element
c.at(n); // safe access, throws error if out of range

operations

list<int> ilist;

// add element at the end
ilist.push_back(10);

// add element on the front.
ilist.push_front(1);

// add element at a specified position
ilist.insert(ilist.begin(), 5); // insert 5 at the beginning
ilist.insert(ilist.end(), 3, 1); // append {1,1,1} at the end

list<int> ilist2 = {1,2,3};
ilist.insert(ilist.end(), ilist2.begin(), ilist2.end()); // add elements from another list
ilist.insert(ilist.end(), {1,2,3});

// emplace construct an object by providing parameters
Object p = Object(arg1, arg2);
vector<Object> vec;
vec.emplace_back(arg1, arg2);
vec.emplace_front(arg1, arg2);
vec.emplace(vec.begin(), arg1, arg2);

// remove elements
ilist.pop_back(); // remove the last element
ilist.pop_front(); // remove the first element
ilist.erase(iter); // remove the element at iter
ilist.erase(ilist.begin()+1, ilist.begin()+2); //remove elements in the range
ilist.clear(); // remove all elements

 // the return of insert and erase is an iterator points the inserting position
auto iter = ilist.begin() + 1;
iter = ilist.insert(iter, 0);
iter = ilist.erase(iter);

resize

vec.resize(10);    

String

Defining and initializing

string s1; // empty string
string s2 = s1;
string s2(s1);
string s4("hello"); // direct initialization
string s3 = "hello"; //copy initialization
string s5(5, 'c'); // "ccccc"
string s6(s1.begin(), s1.end()); // copy of range defined by iterators

Operations

// size
bool b = s.empty();
auto len = s.size(); // return string::size_type

// adding
string s = s1 + s2;
s1 += s2;
s1 = s1 + '\n';

// equality
bool b = s1 == s2;
bool b = s1 != s2;

//characters in string
char c = s[n];
for (auto c: s)
    cout << c << endl;
for (decltype(s.size()) i = 0; i != s.size(); ++i)
    s[i] = toupper(s[i]);

// substr
string sub = s.substr(0,5);

// append
s.append("5th");

// replace
s.replace(11, 3, "abcd"); // replace the substr starts from 11 ends at 11+3

// search
s.find("anna"); // find the first occurrence
s.rfind("anna"); // find the last occurrence
s.find_first_of("abc"); // find the first occurrence of any characters
s.find_last_of("abc"); // find the last occurrence of any characters
s.find_first_not_of("abc");
s.find_last_not_of("abc");

// compare
s1.compare(s2);

Numeric conversions

int i = 42;
string s = to_string(i);
int j = stoi(s);
double d = stod(s);

Vector

Defining and initializing

// initially empty
vector<int> ivec;
vector<Sales_item> Sales_vec;
vector<vector<string>> file;

// initialize by copy
vector<int> ivec2(ivec);
vector<int> ivec3 = ivec;
vector<int> ivec4(ivec.begin(), ivec.end()); // copy of range defined by iterators

// list initializing
vector<string> svec = {"a", "an", "the"};
vector<string> svec{"a", "an", "the"};

// initializing by size
vector<int> ivec(10);   // ten elements, each initialized to 0
vector<string> svec(10);   // ten elements, each initialized to empty string
vector<int> ivec(5, 1); // {1,1,1,1,1}

Operations

v.empty();
v.size();
v.push_back(t);
v[n];
v1 = {a, b, c};
v1 == v2;
v1 != v2;

Built-in Array

Defining and initializing

int arr[10];

constexpr unsigned sz = 3;
int arr[sz]; // the dimension must be a constant expression

int arr[3] = {1,2,3};
int arr[3] = {1,2};       // equals {1,2,0}
int arr[] = {1,2,3};

// no copy or assignment for array

int *ptrs[10];            // ptrs is an array of ten poiters to int
int (*Parray)[10] = &arr; // Parray is a pointer points to an array of ten ints
int (&arrRef)[10] = arr;  // arrRef refers to an array of ten ints
int * (&arry)[10] = ptrs; // reference to an array of ten pointers 

Operations

// size
constexpr size_t sz = sizeof(arr) / sizeof(*arr)

// subdcript
arr[2] = 1;

// traverse
for (auto i : arr)
    cout << i << endl;

Pointers and arrays

int[] arr = {1,2,3};
int * p = arr;          // p points to the first element of arr
int * p = &arr[0];      // equivalent to `int *p = arr`
p + 1                   // points to the subsequent element
p[1]                    // points to the (p + 1) element
int *beg = begin(arr);  // points to the first element of arr
int *end = end(arr);    // points to the end of arr, pasting the last element

Library Array

array<int, 3> arr;  // size is part of the type
array<int, 3> arr = {0, 1, 2};
array<int, 3> arr = {1}; // {1, 0, 0}
array<int, 3> arr1 = arr; // unlike built-in array, can assign and copy as long as the type is the same

Deque

List

Forward_list

Adaptors

  • stack
  • queue
  • Priority_queue

Generic Algorithms

#include <algorithm>

// find
int val = 42;
auto result = find(vec.cbegin(), vec.cend(), val);

// find if
auto wc = find_if(words.begin(), words.end(), 
    [sz](const string &a) {return a.size >= sz; });

// accumulate
#include <numeric>
vector<int> vec = {1,2,3};
int sum = accumulate(vec.cbegin(), vec.cend(), 0);
vector<string> vec = {"a","b","c"};
string sum = accumulate(vec.cbegin(), vec.cend(), string(""));

// equal
equal(roster1.cbegin(), roster1.cend(), roster2.cbegin());

// fill
fill(vec.begin(), vec.end(), 0); // set each element to 0
fill_n(vec.begin(), vec.size(), 0);
fill_n(back_inserter(vec), 10, 0); // append 10 elements to vec

// copy
auto ret = copy(vec.begin(), vec.end(), vec2.begin());

// replace
replace(vec.begin(), vec.end(), 0, 42); // replace the fisrt value with the second

// sort
sort(vec.begin(), vec.end());
// using lambda expression as predicate
sort(vec.begin(), vec.end(), [] (const string &a, const string &b) { return a.size() < b.size()});

// for each
for_each(words.begin(), words.end(), 
    [](const string &s){cout << s << " ";});

// transform
transform(vec.begin(), vec.end(), vec.begin(), 
     [](int i) -> int {return i < 0 ? -i : i});

其他

extern

extern int x; // to obtain a declaration that is not a definition

// const objects are local to file by default, to share const objects across multiple files, we add extern to its definition and declaration.
extern const int bufSize = 512;  // file_1.cpp
extern const int bufSize;        // file_1.h

constexpr

an expression whose value cannot change and that can be evaluated at compile time.

constexpr int mf = 20;
constexpr int limit = mf + 1;

using

#include <iostream>
using std::cin; using std::cout; using std::endl;

#include <string>
using std::string;

// using namespace
using namespace std;

C library

  • name.h in C is called cname in C++
  • inside the std namespace in cname headers
#include <cctype>
int main() {
    string s = "HeLlo";
    for (auto *p : s) {
        if (islower(*p))
            *p = toupper(*p);
    }
    cout << s << endl;
}

Type conversion

  • static_cast
  • dynamic_cast
  • const_cast
  • reinterpret_cast

References