const
const位于星号左侧,const用于修饰指针指向的变量;const位于星号右侧,const修饰指针本身
1 2 3 4 5
| int b = 500; const int* a = &b; [1] int const *a = &b; [2] int* const a = &b; [3] const int* const a = &b; [4]
|
1和2是等价的,都表示指向常量的指针,3表示指针本身不可变,但是指向的内容可变
1 2 3 4 5
| int a = 10; int* const p = &a; *p = 20; int b = 20; p = &b;
|
static
被static修饰的变量只能在当前文件访问,函数同理
1 2 3 4 5 6 7 8 9 10 11 12
| static int a = 10; int main() { a++; return 0; }
extern int a; void foo() { a++; }
|
修饰局部变量
1 2 3 4 5 6 7 8 9 10 11 12
| void foo() { static int count = 0; count++; cout << count << endl; }
int main() { foo(); foo(); foo(); return 0; }
|
extern
用于声明外部变量
File1.c
1 2 3 4 5 6 7 8
| #include <stdio.h>
int globalVar = 42;
void printVar() { printf("globalVar = %d\n", globalVar); }
|
file2.c
1 2 3 4 5 6 7 8
| #include <stdio.h>
extern int globalVar;
void modifyVar() { globalVar = 100; }
|
函数同理,extern还可以链接c和c++,用extern声明一个函数是c语言,则该函数可以在c++文件中使用
c
1 2 3 4 5 6
| #include <stdio.h>
void hello() { printf("Hello from C!\n"); }
|
c++
1 2 3 4 5 6 7 8 9
| #include <iostream>
extern "C" void hello();
int main() { hello(); return 0; }
|
vector
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
| #include<vector>
vector<int> vec1; vector<int> vec2(5); vector<int> vec3(5, 10); vector<int> vec4{1, 2, 3, 4, 5}; vector<int> vec5(vec4);
vec.push_back(x); vec.emplace_back(x); vec.pop_back(); int num = vec.back(); vec.erase(vec.begin() + 1); vec.erase(vec.begin() + 1, vec.edn() - 1); vec.clear(); int n = vec.size(); vec.resize(x); sort(vec.begin(), vec.end()); sort(vec.begin(), vec.end(), greater<int>()); int it = find(vec.begin(), vec.end(), 3); vec.remove(vec.begin(), vec.end(), 5); if (!vec.empty()); int sum = accumulate(vec.begin(), vec.end(), 0) int max_num = *max_element(vec.begin(), vec.end()) vec.insert(vec.end(), vec.begin(), vec.end())
vector<int> vec1 = {1, 2, 3}; vector<int> vec2 = {4, 5, 6}; vec1.insert(vec1.end(), vec2.begin(), vec2.end());
int row = 3; int col = 4; vector<vector<int>> nums(row, vector<int>(4));
|
atoi stoi
1 2 3 4 5 6 7 8 9 10 11 12
| const char* str = "abc";
int result = atoi(str);
try { std::string str = "abc"; int result = std::stoi(str); } catch (const std::invalid_argument& e) { std::cout << "Invalid argument:" << e.what() << std::endl; }
|
stoi提供了更安全的方式
tolower, toupper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <cctype> string str = "Hello World"; string res; for (char ch : str) { res += tolower(ch); } for (char ch : str) { res += toupper(ch); }
for (char ch : str) { ch ^= 32; }
|
unordered_map
哈希表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| unordered_map<char ch, int n> my_map; my_map.insert({'a', 2}); my_map[b] = 1;
for (const auto& pair: my_map) { cout << pair.first << pait.second << endl; }
auto it = umap.find("a"); if (it != umap.end()) { std::cout << "Found: " << it->first << " -> " << it->second << std::endl; } else { std::cout << "Not found!" << std::endl; }
if (umap.count("a") > 0) { std::cout << "Key exists!" << std::endl; }
|
sort
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| vector<int> nums = {2, 3, 1, 0, 4}; sort(nums.begin(), nums.end()); sort(nums.begin(), nums.end(), std::greater());
struct Student { std::string name; int score; };
bool compareStudents(const Student& a, const Student& b) { if (a.score == b.score) return a.name < b.name; return a.score > b.score; }
|
引用和指针
1 2 3 4
| int a = 10; int &b = a; b = 20; cout << a << endl;
|
b是a的引用,就是给a起个别名,对b进行操作实际上就是对a进行操作
指针可以指向空,但是引用不能为空
1 2 3 4
| int a = 10; int &b = a; int c = 30; int &b = c;
|
指针可以随意改变(除const修饰外),引用一旦绑定就不可以再改变
静态链接和动态链接
.cpp文件经过预处理成为.i文件,.i文件经过编译后成为.s文件,.s文件经过汇编后成为目标文件,即.o,静态链接将该.o文件和其他目标文件以及库文件链接起来,这个过程称为静态链接。
而动态链接将这个过程推迟到了运行时,由操作系统装载程序加载库
静态链接的代码装载速度快,但是文件体积大
动态链接的速度慢,但是文件体积小
c和c++的区别
- c只支持基本数据类型,还有结构体、枚举、联合;c++支持类和对象
- c++有封装的特性、有构造函数和析构函数、c++支持函数重载,可以定义同名但是参数列表不同的函数;c都做不到
- c++有异常处理机制;c没有
- c没有引用&
delete
释放new申请的空间,会调用析构函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <iostream>
class MyClass { public: MyClass() { std::cout << "构造函数" << std::endl; } ~MyClass() { std::cout << "析构函数" << std::endl; } };
int main() { MyClass* obj = new MyClass(); delete obj; return 0; }
|
作用域解析操作符
访问全局变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <iostream>
int num = 20;
void test() { int num = 10; std::cout << "test1:" << num << std::endl; std::cout << "test2" << ::num << std::endl; }
int main() { int num = 30; test(); std::cout << "test3:" << num << std::endl; std::cout << "test4:" << ::num << std::endl; return 0; }
|
访问命名空间中的标识符
1 2 3 4 5 6 7 8 9 10
| #include <iostream>
namespace MyNamespace { int val = 20; }
int main() { std::cout << MyNamespace::val << std::endl; return 0; }
|
访问修饰符
public
:可以在任何函数中访问
protected
:只能在类中或者类的子类中访问
private
:只能在类中访问
strlen 和sizeof
1 2 3 4 5
| char ch[] = "Hello World"; std::string str = "Hello World"; std::cout << sizeof(ch) << std::endl; std::cout << strlen(ch) << std::endl; std::cout << sizeof(str) << std::endl;
|
对于char ch[]类型,是c风格的字符串,在末尾会自动加\0
sizeof会统计末尾的\0
strlen不统计
string 和char ch[]
string在堆上分配内存,sizeof获取的是string类的大小
char ch[]在栈上分配内存