C++
Overview
Hello World
#include <iostream>
int main() {
std::cout << "Hello world!" << std::endl;
return 0;
}
Variable & Constants
// variable
int num = 12; // also: `int num(12)`
// constant
const double PI = 3.14;
// multi-var
int x = 3, y = 5;
Notice
局部变量必须初始化:
int num = 0;
较长变量命名规则:使用
_
连接, 如num_short
- 全局变量:初始化为默认值
- 静态局部变量:初始化为默认值
- 自动局部变量:没有被显式初始化时,将保留以前遗留的垃圾值,可能值比较大
#include "iostream"
using namespace std;
int global; // 全局变量:初始化为默认值
int main() {
static int static_local; // 静态局部变量:初始化为默认值
auto int auto_local; // 自动局部变量:没有被显式初始化时,将保留以前遗留的垃圾值,可能值比较大
cout << ::global << endl;
cout << static_local << endl;
cout << auto_local << endl;
return 0;
}
#include <iostream>
int num = 10;
int main() {
int num = 12;
std::cout << ::num << std::endl; // 全局变量:10
std::cout << num << std::endl; // 局部变量:12
return 0;
}
#include "iostream"
void foo();
int main() {
foo();
foo();
foo();
return 0;
}
void foo() {
static int count = 0; // 静态局部变量
count++;
std::cout << "count: " << count << std::endl;
}
/**
* count: 1
* count: 2
* count: 3
*/
#include "iostream"
void foo();
int main() {
foo();
foo();
foo();
return 0;
}
void foo() {
int num = 3;
num++;
auto int count = 0; // 显式自动局部变量
count++;
std::cout << "num: " << num << ", ";
std::cout << "count: " << count << std::endl;
}
/**
* num: 4, count: 1
* num: 4, count: 1
* num: 4, count: 1
*/
Output & Input
output
using namespace std;
// c++
cout << "Hello World!" << endl;
// c
printf("Hello World!\n");
// not to use `using namespace std` in `header file`
输出格式化
/*****************************************
* setprecision(3): 保留小数点后的位数 *
* showpos:显示+- *
* setfill('*'):填充字符 *
* setw(15): 设置值所占字段大小 *
*****************************************/
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
const double PI = 3.14159;
cout << fixed << setprecision(3) << showpos << setfill('*');
cout << setw(15) << left << PI << endl; // +3.142*********
cout << setw(15) << internal<< PI << endl; // +*********3.142
cout << setw(15) << right << PI << endl; // +*********3.142
return 0;
}
input
- cin
using namespace std;
// single var
int x;
cin >> x; // end: space
// multi vars
int a, b;
cin >> a >> b; // connect: use space or line to to separate
- getline
using namespace std;
string s;
getline(cin, s); // end: line
getline(cin, s, '$'); // end: '$'
Data Types
- 整数类型:
int
(short
,long
,unsigned
,signed
修饰) - 浮点类型:
float
,double
(默认), long double - 布尔类型:
bool
- 字符类型:
char
- 字符串类:
string
- 自动类型:
auto
- void(空)类型:显示函数不返回任何值
/* ==== basic type ==== */
int num = 12; // long (L)
double pi = 3.14; // float(F)
bool flag = true; // 1 or 0, boolalpha
char c = 'z';
// string
std::string name;
std::string name = "John Smith";
std::string name("John Smith");
// array
int nums[5] = {1, 2, 3, 4, 5};
int nums[ ] = {1, 2, 3, 4, 5};
//===== STL =====//
// vector
std::vector<int> vec;
std::vector<int> vec = {1, 2, 3};
// map
std::unordered_map<char, int> map;
std::unordered_map<char, int> map = {{'a', 3}, {'b', 2}};
// set
std::unordered_set<int> set;
std::unordered_set<int> set = { 1, 2 };
// auto
auto *ptr = new Solution();
// true(任何非零值) false(0)
// ----output -------- boolalpha ----
bool x = true; // 1 (true)
bool y = 12; // 1 (true)
bool z = false; // 0 (false)
bool e = 0; // 0 (false)
// true输出未1, false输出为0
std::cout << x << std::endl; // 1
std::cout << y << std::endl; // 1
std::cout << z << std::endl; // 0
std::cout << e << std::endl; // 0
// boolalpha: 将布尔值作为字面量(true/false)输出
std::cout << boolalpha;
std::cout << x << std::endl; // ture
std::cout << y << std::endl; // ture
std::cout << z << std::endl; // false
std::cout << e << std::endl; // false
/**
* `sizeof(12)`: 字节大小
* `typeid(12).name()`: 具体类型
* `typeid(3.14+1.2).name()`: 隐式类型转换
* `static_cast<int>(12)`: 显式类型转换
*/
// sizeof
int num = 4
sizeof(num) // sizeof(int): 4
// typeid(expr).name
typeid(12).name() // i
typeid(1.6).name() // d
typeid(3.14f).name() // f
// 隐式类型转换
float pi = 3.14
typeid(pi + 1.2).name() // d: double
// 显式类型转换
double x = 23.6
int y = 30
x + y // 43.6
static_cast<int>(x + y) // 43
// `numeric_limits<int>::max()`: 数据类型最大值
// `numeric_limits<int>::min()`: 数据类型最小值
#include <iostream>
#include <limits>
using namespace std;
int main()
{
cout << "max(int): " << numeric_limits<int>::max() << endl; // max(int): 2147483647
cout << "max(unsigned int): " << numeric_limits<unsigned int>::max() << endl; // max(unsigned int): 4294967295
return 0;
}
Comments
// this is a single comment
/*
this is a multi-line comment
*/
/**
* this is a multi-line comment
*/
Opeartor
/**
* arithmetic operators : + - * / %
* assignment operators : += -= *= /= %=
* increment & Decrement: i++ i-- ++i --i
* comparison operators : == != < > <= >=
* && || !
* a ? b : c
*/
// 判断奇偶
i % 2 == 0
i & 1 == 0
// 中间数
int mid = (l + r) / 2;
int mid = l + (r - l) / 2; // 防溢出
example
int x = 10 / 3; // 3
double t = (2 + 3) / 2; // 2
// `/`除法不会默认保留小数点,除非使用以下两种方式之一
double t = 1.0 * (2 + 3) / 2; // 2.5
double t = static_cast<double>(2 + 3) / 2; // 2.5
x = 5
y = ++x
// x is 6, y is 6
x = 5
y = x++
// x is 6, y is 5
const char *sign = i == nums.size() - 1 ? "" : ", ";
auto sign = i == nums.size() - 1 ? "" : ", ";
Control
If Statement
// 注意: 只要condition != 0 或 false 即通过
if (condition) {
// statement(s)
} else if (condition) {
// statement(s)
} else if (condition) {
// statement(s)
} else {
// statement(s)
}
*Switch Statement
switch (expression) {
case value_1:
// statement(s)
break;
case value_2:
// statement(s)
break;
default:
// statement(s)
}
int day = 6;
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
std::cout << "work day" << std::endl;
break;
case 6:
std::cout << "sta" << std::endl;
break;
default:
std::cout << "sun" << std::endl;
}
For Loop
// default-for
for (init; condition; increment) {
// statement(s)
}
// strong-for
for (auto &v : nums) {
// statement(s)
}
// Notice: pointer loop
// vector
for (auto it = nums.begin(); it != nums.end(); ++it) {
cout << *it << endl;
}
// map
for (auto iter = map.begin(); iter != map.end(); iter++) {
cout << " [" << iter->first << ", " << iter->second << "]";
}
While Loop
while (condition) {
// statement(s)
}
Do While Loop
do {
// statement(s)
} while (condition);
Core
Strings
"Hello" = 'H', 'e', 'l', 'l', 'o', '\0'
, C语言中最后一个字符是字符串结束符'\0'(终止符)
#include <iostream>
#include <string>
int main() {
std::string name = "John Smith";
std::cout << name << std::endl;
std::cout << name.size() << std::endl;
return 0;
}
// if you has included `<iostream>` header file
// #include <string>
// init
std::string s;
std::string s = "Hello World"; // std::string s("Hello World");
// size
.size() // STL
.length() // C
.empty()
// cap
.capacity()
// 增
.push_back(c) // char
.append(s) // substr
.insert(i, s)
// 删
.pop_back()
.clear()
.erase(i) // 删除s[i]后面的所有字符
.erase(i, n) // 删除s[i]后面的n个字符
/* == 查 == */
// index:
.front()
.back()
.at(i) | s[i] | .substr(i, n)
// value
.find(c, pos=0)
.rfind(c, pos=-1)
// 判断
if(s.find(c) != -1) // contains
.ends_with(c | s) // c++20
.starts_with(c | s) // c++20
/* == end == */
// 改
s[i] = c
.replace(start, end, str) // 替换
s1.swap (s2)
.assign(s2)
.assign(s2, n)
.assign(s2.begin(), s2.end())
.assign(n, c) // 前n个字符fill都赋值为c字符
// #include <format>
std::format("The answer is {}.", 42); // c++20
// input
std::getline(std::cin, s);
// sort
std::sort(s.begin(), s.end()); // "hello world!" -> " !dehllloorw"
std::sort(s.begin(), s.end(), std::greater<char>());
// reverse!!
std::reverse(s.begin(), s.end()); // "hello world!" -> "!dlrow olleh"
// string -> int:
stoi(s), stol(s), stoll(s) // 10bit: |x| <= 2147483647, 19bit
// int -> string:
to_string(num)
// string -> byte[]:
.data()
.c_str()
/*
// 比较
s.compare(str)
// 迭代器
s.begin()
s.end()
// 连接
s1 + s2
s1 += s2
*/
// set
for (int i = 0; i < s.size(); ++i) {
s[i] = toupper(s[i]);
}
// set
for (auto &c : s) {
c = toupper(c);
}
// only get
for (char c : s) {
cout << c << endl;
}
#include <cctype>
isalnum(c): 字母或数字
isalpha(c): 字母(a-zA-Z)
isdigit(c): 数字(0-9)
ispunct(c): 特殊字符("$", "*", ...)
isspace(c): 空白字符(" ", "\n", "\t", ...)
islower(c)
isupper(c)
tolower(c)
toupper(c)
// example-1
bool is_ogram(string s);
int main() {
cout << is_ogram("hello") << endl;
}
// example-2
bool is_ogram(string& s);
int main() {
string s = "hello";
cout << is_ogram(s) << endl;
}
stringstream
for example
#include <iostream>
#include <sstream>
using namespace std;
int main() {
stringstream ans;
ans << "hello";
ans << ' ';
ans << "world";
ans << '!';
cout << ans.str() << endl;
// output: "hello world"
}
Array
// init
int nums[5] = {1, 2, 3, 4, 5};
int nums[ ] = {1, 2, 3, 4, 5};
// iter
for (auto &v : nums) {
std::cout << v << " ";
}
Pointer
#include <iostream>
using namespace std;
int main() {
// declare an int pointer
int *ptr = nullptr; // 0x0
// new: dynamically allocate memory
ptr = new int(12); // 0x132e06880, 12
cout << "object address: " << ptr << endl; // 0x142f04080
cout << "pointer address: " << &ptr << endl; // 0x16ae23680
cout << "pointer value : " << *ptr << endl; // 12
// deallocate the memory
delete ptr;
cout << "object address: " << ptr << endl; // 0x142f04080
cout << "pointer address: " << &ptr << endl; // 0x16ae23680
cout << "pointer value : " << *ptr << endl; // 12
ptr = nullptr;
cout << "object address: " << ptr << endl; // 0x0
cout << "pointer address: " << &ptr << endl; // 0x16ae23680
cout << "pointer value : " << *ptr << endl; // No output!
return 0;
}
// C++ Program to store GPA of n number of students and display it
// where n is the number of students entered by the user
#include <iostream>
using namespace std;
int main() {
int n;
cout << "Enter total number of students: ";
cin >> n;
float* ptr;
// memory allocation
ptr = new float[n];
cout << "Enter GPA of students." << endl;
for (int i = 0; i < n; ++i) {
cout << "Student" << i + 1 << ": ";
cin >> *(ptr + i);
}
cout << "\nDisplaying GPA of students." << endl;
for (int i = 0; i < n; ++i) {
cout << "Student" << i + 1 << ": " << *(ptr + i) << endl;
}
// ptr memory is released
delete[] ptr;
ptr = nullptr;
return 0;
}
/*
Enter total number of students: 4
Enter GPA of students.
Student1: 3.6
Student2: 3.1
Student3: 3.9
Student4: 2.9
Displaying GPA of students.
Student1: 3.6
Student2: 3.1
Student3: 3.9
Student4: 2.9
*/
// 空指针
int *p = NULL; // int *p = 0;
p = new int[10];
delete [] p; // delete array pointed
for example
int x = 7;
int *p = &x;
if (p) {}; // true(p非null)
p = 0;
if (p) {}; // false(p为null)
// 通用指针
void *p;
int x = 10;
p = &x;
double y = 12.3;
p = &y;
void swap(int *first, int *second);
int main() {
int x = 10;
int y = 20;
swap(&x, &y);
cout << "x: " << x << " " << "y: " << y << endl;
return 0;
}
void swap(int *pX, int pY)
{
int temp = *pX;
*pX = *pY;
*pY = temp;
}
#include <iostream>
using namespace std;
void printArray(int*, int);
int getSum(const int*, int);
void reverseArray(int*, int);
void printArrays(int (*)[4], int);
int main() {
// 一维数组
// int nums[5] = {2, 4, 1, 3, 7};
// cout << getSum(nums, 5) << endl;
// reverseArray(nums, 5);
// printArray(nums, 5);
// 二维数组
// int matrix[3][4] = {{10, 11, 12, 13},{ 20, 21, 22, 23 },{31, 32, 33, 34}};
// printArrays(matrix, 3);
// 数组指针
int *ptr = new int[5];
int nums[5] = {2, 4, 1, 3, 7};
printArray(nums, 5);
delete[] ptr;
return 0;
}
void printArray(int *p, int size)
{
for (int i = 0; i < size; i++)
{
cout << *(p++) << " ";
}
cout << endl;
}
int getSum(const int *p, int size)
{
int sum = 0;
for (int i = 0; i < size; i++)
{
sum += *(p++);
}
return sum;
}
void reverseArray(int *p, int size)
{
for (int i = 0; i < size / 2; i++)
{
int temp = *(p + size - 1 - i);
*(p + size - 1 - i) = *(p + i);
*(p + i) = temp;
}
}
void printArrays(int(*arr)[4], int rows)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < 4; j++)
{
cout << arr[i][j] << " ";
}
}
cout << endl;
}
Function
void hello(int num);
void hello(int num) {
cout << num;
};
int sum(int x, int y) {
return x + y
};
int area(int x, int y = 1, int z = 2) {
return x + y + 2;
}
#include <iostream>
int add(int a, int b);
double add(double a, double b);
int main() {
add(1, 2);
add(1.6, 2.3);
}
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
function pointer
#include <iostream>
// pass-by-value
void add(int x);
// pass-by-reference
void add_pointer(int& x);
int main() {
int x = 10;
add(x);
std::cout << x << std::endl; // 10
add_pointer(x);
std::cout << x << std::endl; // 11
}
void add(int x) {
x++;
}
void add_pointer(int& x) {
x++;
}
#include <iostream>
// return-by-value
int larger(int x, int y);
// return-by-reference
int& larger(int& x, int& y);
int larger(int x, int y) {
return x > y ? x : y;
}
int& larger(int& x, int& y) {
return x > y ? x : y;
}
STL
vector
#include <vector>
using namespace std;
// method-1
vector<int> vec; // size: 0 value: [ ]
// method-2
vector<int> vec = {1, 2, 3}; // size: 3 value: [ 1, 2, 3 ]
vector<string> vec = {"hello", "world"};
// method-3
// template<class T>
vector<T> vec(n) // size: n value: [ ]
vector<T> vec(n, v) // size: n value: [ v, v, ... ]
// template<>
vector<string> vec{n} // size: n value: ["", "", ... ]
vector<string> vec{n, v} // size: n value: [ v, v, ... ]
// for example
vector<int> v1(3); // size: 3 value: [ 0, 0, 0 ]
vector<int> v2(3, 42); // size: 3 value: [ 42, 42, 42 ]
//vector<int> v3{3, 42}; // size: 2 value: [ 3, 42 ]
// Notice! `template<>`
vector<string> vec{3}; // size: 3 value: [ "", "", "" ]
vector<string> vec{3, "hi"}; // size: 3 value: [ hi, hi, hi ]
methods
// 长度
.size()
.empty() // size() == 0
.resize(n)
// 容量
.capacity()
.reserve(n)
// 查
.front() // vec[0]
nums[i], nums.at(i) // vec[i]
.back() // vec[vec.size()-1]
// 增
.push_back(e) // vec.push_back(v)
.insert(nums.bengin()+2, e) // vec[2] = e
// 删
.pop_back()
nums.erase(nums.begin(), nums.begin()+2);
.clear()
// 改
v1.swap(v2) // 两者所有元素值交换
v2.assign(v1.begin(), v1.end()) // 复制v1的元素值到v2中
// sort
std::sort(nums.begin(), nums.end())
std::sort(nums.begin(), nums.end(), std::greater<T>())
std::sort(nums.begin(), nums.end(), [&](T x, T y) -> bool {return x > y;})
std::reverse(nums.begin(), nums.end())
count(nums.begin(), nums.end(), e) // count: [0, ...]
// max
std::max_element(nums.begin(), nums.end())
// min
std::min_element(nums.begin(), nums.end())
// contains
template<typename T>
bool contains(vector<T> nums, T target) {
return std::find(nums.begin(), nums.end(), target) != nums.end();
}
// upper_bound 二分查找第一个小于等于e的值的地址
// auto it = upper_bound(nums.begin(), nums.end(), e)
int index = upper_bound(nums.begin(), nums.end(), e) - nums.begin()
int value = *upper_bound(nums.begin(), nums.end(), e)
遍历
for (int i = 0; i < nums.size(); i++) {
cout << nums[i] << endl;
}
for (auto& v: nums) {
cout << v << " ";
}
for (auto it = nums.begin(); it != nums.end(); ++it) {
cout << *it << endl;
}
map
#include <unordered_map>
// init
std::unordered_map<char, int> map
std::unordered_map<char, int> map = {{'a', 3}, {'b', 2}}
// size, cap
.size()
.empty()
// 增
map[k] = v // better!!
// map.insert({k, v})
// 删
.erase(k)
.clear()
// 查
map[k] // notice: 查询map[k] 会新增key! at(k)则不会
map.at(k)
// .count(k) // [0, 1]
// .find(k)
.contains(k) // c++20
// `if (map.find(k) != map.end())`
// `if (map.count(k))`
// `if (map[k])` 也会新增key, value为初始值
// 遍历
for (auto& it : map) {
std::cout << " [" << it.first << ", " << it.second << "]";
}
std::cout << std::endl;
for (auto it = map.begin(); it != map.end(); it++) {
std::cout << "[" << it->first << ", " << it->second << "] ";
}
std::cout << std::endl;
example
#include <iostream>
#include <unordered_map>
template<typename T, typename U>
void display_map(const std::unordered_map<T, U>& map);
int main() {
using namespace std;
// init
unordered_map<char, int> map;
// unordered_map<char, int> map = {{'a', 3}, {'b', 2}};
// 增
map.insert({'a', 1});
map['b'] = 2;
display_map(map); // [b, 2] [a, 1]
cout << map.size() << endl; // 2
// 查: map[k] 会新增key,at(k)则不会
cout << map['a'] << endl; // 1
cout << map['b'] << endl; // 2
cout << map['c'] << endl; // 0
cout << map.at('a') << endl; // 1
cout << map.at('c') << endl; // 0
display_map(map); // [c, 0] [b, 2] [a, 1]
// size
cout << map.size() << endl; // 3
cout << boolalpha;
cout << map.empty() << endl; // false
// count
map = {{'a', 1}, {'b', 2}, {'c', 3}};
display_map(map);
cout << map.count('a') << endl; // 1
cout << map.count('b') << endl; // 1
cout << map.count('c') << endl; // 1
cout << map.count('d') << endl; // 0
display_map(map);
// find
cout << (map.find('a') != map.end()) << '\n'; // true
cout << (map.find('k') != map.end()) << '\n'; // false
// contains (c++20)
cout << map.contains('a') << '\n'; // true
cout << map.contains('k') << '\n'; // false
return 0;
}
template<typename T, typename U>
void display_map(const std::unordered_map<T, U> &map) {
// for (auto& it : map) {
// cout << " [" << it.first << ", " << it.second << "]";
// }
// cout << endl;
for (auto it = map.begin(); it != map.end(); it++) {
std::cout << "[" << it->first << ", " << it->second << "] ";
}
std::cout << std::endl;
}
set
#include <unordered_set>
std::unordered_set<int> set;
std::unordered_set<char> set = { 'a', 'c' };
// size
.size()
.empty()
// 增
.insert(e)
// 删
.erase(e)
.clear()
// 查
*(set.find(e)) // value
.count(e) // [0. 1]
.contain(e) // c++20 equal to `if(set.find(e) != set.end())` or `if (count(e))`
if(set.insert(e).second) {
cout << "success to insert!";
}
// 改
.swap(set2)
// iter
template<typename T>
void display_set(const std::unordered_set<T>& set) {
for (auto& it : set) {
if (isalpha(it)) std::cout << "[" << char(it) << "] ";
else std::cout << "[" << it << "] ";
}
std::cout << std::endl;
}
example
#include <iostream>
#include <unordered_set>
#include <cctype>
template<typename T>
void display_set(const std::unordered_set<T>& set);
int main() {
std::unordered_set<int> set;
// add
set.insert('a');
set.insert('b');
set.insert('c');
// size
std::cout << set.size() << '\n'; // 3
std::cout << set.empty() << '\n'; // 0
display_set(set); // [c] [b] [a]
// remove
set.erase('d'); // no error if element not exists
set.erase('c'); // [b] [a]
set.clear();
// contains
set = {'a', 'b', 'c', 'd'};
std::cout << std::boolalpha;
std::cout << set.contains('k') << '\n'; // false
std::cout << set.contains('c') << '\n'; // true
std::cout << (set.find('c') != set.end()) << '\n'; // true
std::cout << (set.find('k') != set.end()) << '\n'; // false
std::cout << (set.count('c') != 0) << '\n'; // true
display_set(set); // [d] [c] [b] [a]
// count
std::cout << set.count('c') << '\n'; // 1
std::cout << set.count('k') << '\n'; // 0
// find
auto it = set.find('b');
std::cout << char(*it) << std::endl; // 'b'
// swap
std::unordered_set<int> set1 = {1, 3, 6};
std::unordered_set<int> set2 = {2, 4, 7};
set1.swap(set2);
display_set(set1); // set1: [4] [7] [2]
display_set(set2); // set2: [3] [6] [1]
std::cout << __cplusplus << std::endl; // 202002
return 0;
}
template<typename T>
void display_set(const std::unordered_set<T>& set) {
for (auto& it : set) {
if(isalpha(it)) std::cout << "[" << char(it) << "] ";
else std::cout << "[" << it << "] ";
}
std::cout << std::endl;
}
stack
#include <stack> // 先进后出
size()
empty()
增:push()
查:top()
删:pop()
example
#include <iostream>
#include <stack>
using namespace std;
void print_stack(stack<int> stack1);
int main() {
stack <int> stack1;
stack1.push(1);
stack1.push(3);
stack1.push(5);
stack1.push(9);
cout << "size: " << stack1.size() << endl; // 4
cout << boolalpha;
cout << "empty: " << stack1.empty() << endl; // false
int& i = stack1.top();
cout << "top: " << i << endl;
stack1.pop();
cout << "top(after pop): " << stack1.top() << endl;
print_stack(stack1);
return 0;
}
void print_stack(stack<int> stack) {
cout << "stack: [ ";
while(!stack.empty()) {
auto sign = stack.size() > 1 ? ", " : " ";
cout << stack.top() << sign;
stack.pop();
}
cout << "]" << endl;
}
deque
#include <deque>
std::deque<int> d;
std::deque<int> d = {1, 3, 5, 7};
// 长度
size()
empty()
// 查
front()
d[i], d.at(i)
back()
// 增
push_front(e)
insert(pos, e)
push_back(e)
// 删
pop_front()
pop_back()
erase(pos1, pos2)
clear()
// 改
d[i] = e
// iterator
cout << "[ "
for (int i = 0; i < d.size(); ++i) {
cout << d[i] << " ";
}
cout << "]" << endl;
// pointer_iter
begin()
rbegin()
cout << *(d.begin()+1); // d[1], 超出索引取默认值
example
#include <iostream>
#include <deque>
int main() {
using namespace std;
deque<int> d = {1, 3, 5, 7};
// size
cout << d.size() << endl; // 4
cout << d.max_size() << endl; // 4611686018427387903
cout << d.empty() << endl; // 0 (false)
// element access
cout << d.at(0) << endl; // d[0]: 1
cout << d[0] << endl; // d[0]: 1
cout << d.front() << endl; // first element: 1
cout << d.back() << endl; // last element: 7
// 超过索引范围则输出为默认值
cout << "begin: " << *(d.begin()) << endl; // d[0]: 1
cout << "begin: " << *(d.begin()+1) << endl; // d[1]: 3
cout << "rbegin: " << *(d.rbegin()) << endl; // d[-1]: 7
cout << "rbegin: " << *(d.rbegin()+1) << endl; // d[-2]: 5
// add element
d.push_front(0);
d.insert(d.begin()+2, 2);
d.push_back(9);
// 0 1 2 3 5 7 9
// remove element
d.erase(d.begin()+2, d.begin()+4); // del d[2:4)
// 0 1 5 7 9
// d.clear();
// iterator
cout << "[ ";
for (int i = 0; i < d.size(); ++i) {
cout << d[i] << " ";
}
cout << "]" << endl;
return 0;
}
list
#include <iostream>
#include <list>
int main() {
using namespace std;
std::list<int> l = { 7, 5, 16, 8 };
l.size();
l.empty();
l.push_front(25);
l.push_back(13);
// { 25, 7, 5, 16, 8, 13 }
l.sort(); // { 5 7 8 13 16 25 }
l.splice(l.begin(), {12,3}); // { 12 3 5 7 8 13 16 25 }
l.merge({12,2}); // { 12 3 5 7 8 12 2 13 16 25 }
// iterator
cout << "{ ";
for (int &it : l) {
cout << it << " ";
}
cout << "}" << endl;
return 0;
}
OOP
class example
#include <iostream>
class BankAccout {
public:
void sayHi() {
std::cout << "Hi" << std::endl;
}
};
int main() {
// instantiation
BankAccout back;
// function call
back.sayHi();
// pointer call 1
BankAccout back2;
BankAccout *ptr = &back2;
ptr->sayHi();
// pointer call 2
auto *ptr2 = new BankAccout();
ptr2->sayHi();
return 0;
}
Encapsulation (封装)
- public
- private
- protected
- friend
#include <iostream>
class student {
private:
std::string name;
public:
void setName(std::string x) {
name = x;
// this->name = x;
// (*this).name = x;
}
std::string getName() {
return name;
}
protected: // ...
// friend function
};
int main() {
student *ptr = new student;
ptr->setName("John Smith");
std::cout << ptr->getName() << std::endl;
delete ptr;
return 0;
}
内联函数
class Circle {
private:
double radius;
public:
// 隐式内联函数
double getRadius() {
return radius;
}
};
class Circle {
private:
double radius;
public:
double getRadius();
};
// 显式内联函数
inline double Circle::getRadius {
return radius;
}
struct & class
// struct 结构所有成员默认都是公共的
struct student {
int age;
char *name[20];
}
// class 类所有成员默认都是私有的
class student {
private:
int age;
string name;
}
Constructor & Destructor
#include <iostream>
class Circle {
public:
Circle(); // 默认构造函数(无参)
Circle(double r); // 参数构造函数
Circle(const Circle& c); // 拷贝构造函数
~Circle(); // 析构函数
private:
double radius;
};
// 默认无参构造函数
Circle::Circle():radius(0.0) // 如果省略,则设置为垃圾值
{
}
// 参数构造函数
Circle::Circle(double r):radius(r)
{
}
// 拷贝构造函数
Circle::Circle(const Circle& c):radius(c.radius)
{
}
// 析构函数
Circle::~Circle()
{
}
int main() {
Circle circle1;
Circle circle2(3.0);
Circle circle3(circle1);
return 0;
}
/*
default constructor
params constructor
copy constructor
destructor
destructor
destructor
*/
int main() {
Circle *ptr = new Circle(); // Constructor
delete ptr; // Destructor
return 0;
}
int main() {
Circle obj(10.0); // Destructor
return 0;
}
// 默认会提供合成无参构造函数、析构函数、copy constructor
// 如果自行设置了默认无参构造函数或参数构造函数,则不会再提供合成默认无参构造函数.
// 阻止使用拷贝构造函数
Circle(const Circle& c) = delete;
this
double getRadius() const {
return radius;
}
// 隐式this指针
double getRadius(Circle* this) const {
return this->radius; // 与(*this).radius相同
}
void Circie::setRadius(double r) {
radius = r;
}
// 显式this指针 (无需缩写参数名称)
void Circle::setRadius(double radius) {
this->radius = radius;
}
const
class Circle {
private:
double radius;
public:
double getRadius() const; // getter 访问器 设置const限定符确保宿主对象(this指向的对象)为只读
void setRadius(double r); // setter 更改器 不能设置常量限定符const
};
static
#include <iostream>
class Rectangle {
private:
static int count; // static 静态数据成员
public:
static int getCount(); // static 静态成员方法
};
int Rectangle::count = 0;
int Rectangle::getCount() {
return count;
}
int main() {
// static call
Rectangle::getCount();
Rectangle rect;
rect.getCount();
return 0;
}
独立文件编译
c++ -c circle.cpp
c++ -c app.cpp
c++ -o app circle.o app.o
./app
rm -f circle.o app.o app
// circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include <iostream>
#include <cassert>
class Circle {
private:
double radius;
public:
Circle(); // 默认构造函数(无参)
Circle(double r); // 参数构造函数
Circle(const Circle& c); // 拷贝构造函数, Circle(const Circle& c) = delete; // 阻止使用拷贝构造函数
~Circle(); // 析构函数
void setRadius(double r); // setter 更改器
double getRadius() const; // getter 访问器
double getArea() const;
double getPerimeter() const;
};
#endif //CIRCLE_H
// circle.cpp
#include "circle.h"
// 默认无参构造函数
Circle::Circle():radius(0.0) // 如果省略,则设置为垃圾值
{
std::cout << "default constructor" << std::endl;
}
// 参数构造函数
Circle::Circle(double r):radius(r)
{
std::cout << "params constructor" << std::endl;
if (radius < 0.0) assert(false);
}
// 拷贝构造函数
Circle::Circle(const Circle& c):radius(c.radius)
{
std::cout << "copy constructor" << std::endl;
}
// 析构函数
Circle::~Circle()
{
std::cout << "destructor" << std::endl;
}
void Circle::setRadius(double r)
{
radius = r;
if (radius < 0.0) assert(false);
}
double Circle::getRadius() const
{
return radius;
}
double Circle::getArea() const
{
const double PI = 3.14;
return radius * radius * PI;
}
double Circle::getPerimeter() const
{
const double PI = 3.14;
return radius * PI * 2;
}
// app.cpp
#include "circle.h"
#include <iomanip>
using namespace std;
int main() {
Circle c(5.2);
cout << " radius area perimeter " << endl;
cout << " --------- ----------- ------------" << endl;
cout << setw(9) << right << c.getRadius();
cout << setw(15) << c.getArea();
cout << setw(13) << c.getPerimeter();
cout << endl;
return 0;
}
/*
radius area perimeter
--------- ----------- ------------
5.2 84.9056 32.656
*/
Inheritance (继承)
class Cat : public Animal {}; // 继承
class Person {};
class Student : virtual public Person {}; // 虚继承
class Professor : virtual public Person {};
class TA : public Professor, public Student {}; // 多重继承
example
#include <iostream>
class Product
{
protected:
double price;
int weight;
public:
void getInfo() const {
std::cout << price << ", " << weight;
}
};
class Fruit : public Product
{
public:
std::string type;
void setInfo(double price, int weight) {
// Base class data call
this->price = price;
this->weight = weight;
}
/*
void setInfo(double p, int w) {
price = p;
weight = w;
}
*/
};
int main() {
Fruit obj;
obj.type = "Apple";
// Base class method call
obj.setInfo(4.99, 10);
obj.getInfo();
return 0;
}
#include <iostream>
class Person {
protected:
std::string name;
public:
Person(std::string name);
~Person();
};
// 虚继承
class Student : virtual public Person {
protected:
double gpa;
public:
Student(std::string name, double gpa): Person(name), gpa(gpa){};
~Student();
};
class Professor : virtual public Person {
protected:
double salary;
public:
Professor(std::string name, double salary): Person(name), salary(salary){};
~Professor();
};
// 多重继承
class TA : public Professor, public Student {
public:
TA(std::string name, double gp, double sal): Person(name), Student(name, gp), Professor(name, sal){};
~TA();
};
Polymorphism (多态)
class Animal {};
class Cat : public Animal {};
class Dog : public Animal {};
class Person {};
class Student : virtual public Person {}; // 虚继承
class Professor : virtual public Person {};
class TA : public Professor, public Student {}; // 多重继承
#include <iostream>
class Animal {
protected:
int age;
public:
// 显式虚析构函数
~Animal(){};
// virtual (虚函数)
virtual void speak() {
std::cout << "In Animal" << std::endl;
}
};
class Cat : public Animal {
public:
void speak() {
std::cout << "In Cat"<< std::endl;
}
};
class Dog : public Animal {
public:
void speak() {
std::cout << "In Dog"<< std::endl;
}
};
int main() {
Animal *ptr;
ptr = new Animal();
ptr->speak(); // In Animal
delete ptr;
ptr = new Cat();
ptr->speak(); // In Cat
delete ptr;
ptr = new Dog();
ptr->speak(); // In Dog
delete ptr;
return 0;
}
error(no virtual)
#include <iostream>
class Animal {
protected:
int age;
public:
// 显式虚析构函数
~Animal(){};
void speak() const {
std::cout << "In Animal" << std::endl;
}
};
class Cat : public Animal {
public:
void speak() {
std::cout << "In Cat"<< std::endl;
}
};
class Dog : public Animal {
public:
void speak() {
std::cout << "In Dog"<< std::endl;
}
};
int main() {
Animal *ptr;
ptr = new Cat();
ptr->speak(); // In Animal
delete ptr;
ptr = new Dog();
ptr->speak(); // In Animal
delete ptr;
return 0;
}
Abstract (抽象)
Pure virtual function cannot be overridden.
virtual void speak() = 0;
#include <iostream>
// pure-virtual function:
// 1. cannot create object of the base class
// 2. if delete the base class pointer, cannot print the next derived class function.
class Animal {
protected:
int age;
public:
~Animal(){};
// pure virtual method
virtual void speak() = 0;
};
class Cat : public Animal {
public:
void speak() {
std::cout << "In Cat"<< std::endl;
}
};
class Dog : public Animal {
public:
void speak() {
std::cout << "In Dog"<< std::endl;
}
};
int main() {
Animal *ptr;
// ptr = new Animal(); // error
ptr = new Cat();
ptr->speak(); // In Cat
// delete ptr; // if has it, only print "In Cat"
ptr = new Dog();
ptr->speak(); // In Dog
delete ptr;
return 0;
}
File
#include <iostream>
#include <fstream>
using namespace std;
int main() {
int sum(0);
int num;
ifstream infile;
infile.open("numbers.dat");
while(infile >> num) {
sum += num;
}
cout << "The sum of the numbers in the file is " << sum << endl; // 1500
infile.close();
return 0;
}
100
200
300
400
500
FAQ
cpp version
cpp version
cout << __cplusplus << endl; // 2020-02
change cpp version
# CMakeLists.txt
set(CMAKE_CXX_STANDARD 20)
clang version
$ clang --version
i++ & ++i
尽量使用++i来代替i++的自增序列
#include<iostream>
using namespace std;
class increment {
int x_;
int y_;
public:
increment(int x = 0, int y = 0);
increment(const increment&);
~increment();
increment& operator++();//前置
const increment operator++(int);//后置
increment operator+(const increment&);
increment& operator+=(const increment&);
void Displayincrement();
};
increment& increment::operator+=(const increment& _right)
{
this->x_ += _right.x_;
this->y_ += _right.y_;
return *this;
}
increment increment::operator+(const increment& _right)
{
increment temp;
temp.x_ = this->x_ + _right.x_;
temp.y_ = this->y_ + _right.y_;
return temp;
}
increment& increment::operator++()
{
++x_;
++y_;
return *this;
}
const increment increment::operator++(int)
{
increment temp(*this);
this->x_++;
this->y_++;
return temp;
}
increment::increment(int x, int y)
{
x_ = x;
y_ = y;
cout << "this is constructor" << endl;
}
increment::increment(const increment& b)
{
this->x_ = b.x_;
this->y_ = b.y_;
cout << "this is copy constructor" << endl;
}
increment::~increment()
{
cout << "this is destructor" << endl;
}
void increment::Displayincrement()
{
cout << "x: " << this->x_ << endl;
cout << "y: " << this->y_ << endl;
}
int main()
{
increment i(1, 1);
cout << endl << "this is i++: " << endl;
i++;
cout << endl << "this is ++i: " << endl;
++i;
cout << "end" << endl;
return 0;
}
/*
this is constructor
this is i++:
this is copy constructor
this is destructor
this is ++i:
end
this is destructor
*/
using namespace std & std::cout
尽量不要在头文件中使用
using namespace std;
语句, 可以直接使用std::cout
这样不容易发生命名冲突.namespace 命名空间避免不同头文件中的冲突, 并提供其他区分方法.例如std::string, cstring::string
method-1
#include <iostream>
using namespace std;
int main() {
cout << "Hello world!" << endl;
return 0;
}
method-2
#include <iostream>
int main() {
std::cout << "Hello world!" << std::endl;
return 0;
}
NULL, nullptr, 0 ?
本来C可以允许int *a = (void *)0;
但是到了C++就不允许了,因为C不允许void * 给别的指针类型作右值,所以C++只能把NULL定义成0。即NULL是0,
所以NULL既是整型又是空指针常量,这就会导致出现二义性,这是个坑,
所以C++又新出了一个关键字nullptr,以后只用nullptr,从此NULL就可以慢慢被C++抛弃了
// c
#define NULL ((void*)0)
// cpp
#define NULL 0
/* source code */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
usage
int *p = 0;
int *p = NULL;
int *ptr = nullptr; //推荐使用
if (ptr == nullptr) {}
if (ptr == NULL) {}
if (ptr == 0) {}
// nullptr 还可以抛出异常
Tips
- output: 格式化使用C的
printf()
方法 - datatype: 长数据类型使用auto省略
- switch: 多个case, condition必须是boolean(int, char, bool...)不能是字符串(string, char*)
- for loop: auto
&
v修改 - pointer: 推荐使用
nullptr
(C++11)