初识c++
1. 2023/7/13
1.1. Contribut
- 剑桥雅思真题
- manium数学动画
- https://github.com/
- public/private/protected cpp
- friend cpp
- non-virtual function cpp
1
2virtual void example () {
}const = 0;
2. 2023/7/14
2.1. cpp learning
stringstream
used to split wordusing namespace std;
to_string(int):change a int to a string
仅作测试样例
1
2
3
4int main()
{
printf("%-3d",a);
}-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52class Solution {
struct Trie {
bool isEnd;
vector<Trie*> children;
Trie() : isEnd(false), children(26, NULL){}
};
string searhPrefix(Trie* root, const string& word) {
Trie* cur = root;
string res;
for (char c : word) {
if (cur->children[c - 'a'] == NULL) {
return "isNotMatch";
}
res += c;
cur = cur->children[c - 'a'];
if (cur->isEnd == true) return res;
}
return "isNotMatch";
}
public:
string replaceWords(vector<string>& dictionary, string sentence) {
// 构建前缀树Trie
Trie* root = new Trie();
for (string& str : dictionary) {
Trie* cur = root;
for (char c : str) {
if (cur->children[c - 'a'] == NULL) {
cur->children[c - 'a'] = new Trie();
}
cur = cur->children[c - 'a'];
}
cur->isEnd = true;
}
// 分割字符串
string word, res;
stringstream input(sentence);
while (input >> word) {
// 查找前缀prefix
string prefix = searhPrefix(root, word);
if (prefix != "isNotMatch") {
res += prefix;
} else {
res += word;
}
res += " ";
}
res.pop_back();
return res;
}
}; nullptr 纯右值(need to study)
预编译->编译(目标文件obj,机器代码,可通过译码变为汇编指令)->链接
using Func = int (*)(int,int) 函数指针
using 和 typedef 的区别在于typedef只能定义类型别,,using可以定义模板别名
3. 2023/7/20
1 |
|
- using PI = pair<Treenode*,__uint128_t>;
- push_back() vs emplace_back()
push_back时vector会新建一个数组,将新元素&原vector中的元素深拷贝至新vector,原vector会被释放, 其中元素的析构函数也会被调用
注意: 这里只适用于没有创建固定大小空间的vector,若使用vector.reverse(N),提前创建好元素个数,可以提高存取速度
使用Reserve()而不是使用“vectorvertices(3)”,因为下面的语法有时不起作用,因为类中没有定义默认构造函数。 使用emplace_back而不是使用参数化构造函数创建对象并将其分配到不同的内存中,然后将其传递给复制构造函数,复制构造函数会将其插入到向量中。该函数可以直接插入对象,无需调用复制构造函数。
如果构造函数接受多个参数,push_back 只接受该类型的一个对象obj, 而emplace_back 接受该类型的构造函数的参数。
4. 2023/7/24
- vector empty是常数时间,empty()函数没有使用任何比较运算符,因此使用起来更方便,无论容器类型如何, empty() 函数都以恒定时间实现,而 size() 函数的某些实现需要 O(n) 时间复杂度,例如 list::size()。
- size返回参数为size_t(unsigned int type),要小心其在vecotr.size()-1上使用时出现小于0的情况出现段错误的情况
- Base(const Base& temp_obj) = delete;
- 列表初始化(list initalize)
vector<int> vec{1}
vector<pair<int,int>> vec{{1,1}}
vector<pair<int,int>> vec{make_pair(1,1)}
not the vec{(1,1)},it’s evaluated as 1
- 逗号运算符,它是一种中缀运算符,用于对其左右两个表达式进行求值,并返回第二个表达式的值。
- 使用声明将基类的成员引入到派生类定义中,例如将基类的受保护成员公开为派生类的公共成员。在这种情况下,nested-name-specifier必须命名所定义的基类。如果名称是基类的重载成员函数的名称,则引入具有该名称的所有基类成员函数。如果派生类已具有具有相同名称、参数列表和限定条件的成员,则派生类成员将隐藏或覆盖(不冲突)从基类引入的成员。
- protected关键字说明成员在派生类中是可见的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include <iostream>
struct B
{
virtual void f(int) { std::cout << "B::f\n"; }
void g(char) { std::cout << "B::g\n"; }
void h(int) { std::cout << "B::h\n"; }
protected:
int m; // B::m is protected
typedef int value_type;
};
struct D : B
{
using B::m; // D::m is public
using B::value_type; // D::value_type is public
using B::f;
void f(int) { std::cout << "D::f\n"; } // D::f(int) overrides B::f(int)
using B::g;
void g(int) { std::cout << "D::g\n"; } // both g(int) and g(char) are visible
using B::h;
void h(int) { std::cout << "D::h\n"; } // D::h(int) hides B::h(int)
};
int main()
{
D d;
B& b = d;
// b.m = 2; // Error: B::m is protected
d.m = 1; // protected B::m is accessible as public D::m
b.f(1); // calls derived f()
d.f(1); // calls derived f()
std::cout << "----------\n";
d.g(1); // calls derived g(int)
d.g('a'); // calls base g(char), exposed via using B::g;
std::cout << "----------\n";
b.h(1); // calls base h()
d.h(1); // calls derived h()
} - 聚合初始化(aggregate initialization)
- 指定初始化器(designated initializers)
- four types of initializers:
- T object{d,s,i} brace elision is prohibited 直接列表初始化
- T object={d,s,i} 复制初始化
头文件规定了uint32_t & so on
5. 2023/7/25
1 |
|
- c++文件与流
- cin 与 cin.get()都会将分隔符留在输入缓冲区中
- c++ getline
- getline分为两类:
std:getline string流里的 std:basic_istream isstream流里的,主要用来提取C string getline(cin,str,delim) cin.getline(streamsize,delim) 存储的字符大于str.max_size()或者碰到分隔符会结束提取字符 存储的字符等于streamsize-1或者碰到分隔符会结束提取字符 分割符会被提取但不会被存储 分隔符会被提取同时被计数
- getline分为两类:
- memcpy & memmove
1
2memcpy(array.data(),str,bytessize) //拷贝指定字节数至des
memmove(array.data()/des,str/src,bytessize) //当src+bytessize和des有重叠字节时用memmove
6. 2023/7/26
queue,stack等adapter列表初始化时不能直接使用brace,要先使用brace将其转化为底层容器,再用小括号将其转化为adapter
queuemyqueue({1,2,3}) 同一行不能用逗号隔开两个不同类型变量的定义或声明
并查集的标准写法
- 私有成员成员vector也可以通过列表成员初始化进行初始化
- iota:对序列中的元素进行值递增操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36class UF {
public:
vector<int> fa;
vector<int> sz;
int n;
int comp_cnt;
public:
UF(int _n): n(_n), comp_cnt(_n), fa(_n), sz(_n, 1) {
iota(fa.begin(), fa.end(), 0);
}
int findset(int x) {
return fa[x] == x ? x : fa[x] = findset(fa[x]);
}
void unite(int x, int y) {
x = findset(x);
y = findset(y);
if (x == y) {
return;
}
if (sz[x] < sz[y]) {
swap(x, y);
}
fa[y] = x;
sz[x] += sz[y];
--comp_cnt;
}
bool connected(int x, int y) {
x = findset(x);
y = findset(y);
return x == y;
}
};
结构化绑定
- auto [x, y] = q.front();//无需使用q.front().first
vector.erase(std::unique(vector.begin(), vector.end()),vector.end());