(1)命名空间有局域性
void test1(void)
{
using namespace std;//作用域只局限在{}内
cout << "hello" << endl;
}
(2)数组
1>数组的初始化可去掉=
int tab[4] {1,2,3,4};
int tab1[4] {};//默认为0
2>数组的替代
《1》vector:存储方案是使用new 和delete进行的管理,也就是说数据是在堆区和自由存储区,使用起来效率相对低
《2》array:申请时就确定大小,效率高,和数组相同
(3)vector 循环遍历
1> for (auto& x : list)
typedef struct MyDa {
std::string name;
int age;
};
void test1(void)
{
using namespace std;
MyDa test;
vector<MyDa> list;
test.name = "kjlkjkl";
test.age = 1233;
list.push_back(test);
for (auto& x : list)
{
cout << "x = " << x.name << endl;
cout << "x = " << x.age << endl;
}
}
2>
(4)内存的申请和释放,new和delete
和c使用一样,唯一区别是申请和释放数组
int *p = new int [500];
delete [] p;//方括号是告诉程序是释放整个数组,不是指向的元素;
int * p1 = new int;
delete p1;
总结:
可以简单记住是申请是带有[],则释放时带有[],申请时没有[],则释放时没有[]
(5)程序内存的分配
C++程序的内存格局通常分为四个区:全局数据区(data area),代码区(code area),栈区(stack area),堆区(heap area)(即自由存储区)。
全局数据区存放全局变量,静态数据和常量;
所有类成员函数和非成员函数代码存放在代码区;
为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区
余下的空间都被称为堆区。
(6)类中如何实现调用方法
个人理解:每个方法会根据类的命名空间,所属类,以及参数类型,返回值类型来确定这个函数的唯一性,编译阶段会由编译器更改方法名字,然后在编译器中生成一个对应的全局函数,这个生成方法是可逆的,也就是说在调用方法时可找到这个对应的全局函数,知道全局函数就可以找到这个类方法。而且在这个全局函数中会自动增加一个对象传参指针this,这个对象中只包含类的成员和虚函数表,这也就是为什么在方法中可以调用this指针
(7)虚函数使用
#include <iostream>
#include <climits>
#include <vector>
using namespace std;
class A
{
public:
virtual void foo()
{
cout << "A::foo() is called" << endl;
}
};
class B :public A
{
public:
void foo()
{
cout << "B::foo() is called" << endl;
}
};
int main(void)
{
A* a = new B();
a->foo(); // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!
return 0;
}
打印结果:B::foo() is called
(8)智能指针
参考https://www.cnblogs.com/WindSun/p/11444429.html
理解:对于使用new生成的对象,把释放权限交给智能指针,而智能指针是通过作用域和引用计数来管理释放时机
1>unique_ptr ,对象被管理后,不能再被其他智能指针管理,在超出指针的作用域后,自动释放
2>shared_ptr,可以多个智能指针管理同一个对象,每个指针作用域失效后,引用就减1,直到为0,被管理对象被释放
2.1>weak_ptr,用于辅助shared_ptr,因为shared_ptr可能会出现互相引用的死锁情况,而weak_ptr简单可以理解为和shared_ptr用相同功能,但是在被管理时,引用没有增加,释放没有减少,也就会出现和shared_ptr引用相差1,就不会出现死锁情况了