C++11 auto_ptr 被废弃与 unique_ptr

一、auto_ptr 特点 支持拷贝构造 支持赋值拷贝 支持 operator->/operator* 解引用 支持指针变量重置 保证指针持有者唯一(涉及所有权转移) 二、问题一:使用数组存储 auto_ptr std::vector<std::auto_ptr<People>> peoples; // 这里实例化多个people并保存到数组中 ... std::auto_ptr<People> one = peoples[5]; ... std::cout << peoples[5]->get_name() << std::endl; 原因在于 std::auto_ptr 支持 operator=,为了确保指针所有者唯一,这里转移了所有权,people[5] 变成了 null 三、问题二、函数传参 auto_ptr 类型 void do_somthing(std::auto_ptr<People> people){ // 该函数内不对people变量执行各种隐式/显示的所有权转移和释放 ... } std::auto_ptr<People> people(new People("jony")); do_something(people); ... std::cout << people->get_name() << std::endl; 原因在于 std::auto_ptr支持拷贝构造,为了确保指针所有者唯一,这里转移了所有权 四、unique_ptr 在11中,可以支持右值以及移动语义了,此时可以完全匹配auto_ptr的所有权管理,新增了 std::unique_ptr。std::unique_ptr 不仅加入了移动语义的支持,同时也关闭了左值拷贝构造和左值赋值功能!杜绝了上述场景的出现!但是,此时,需要使用其他的方案了。比如场景一中,std::unique_ptr类型变量不能使用vector保存了! 所以 std::auto_ptr 废弃了,由 std::unique_ptr 代替! class Person{ public: int getAge()const{ return m_age; } void setAge(int age){ m_age = age; } private: int m_age{20}; }; unique_ptr<Person> Change(unique_ptr<Person> p){ p->setAge(30); return p; } int main() { unique_ptr<Person> pP(new Person); cout << pP->getAge() << endl; // unique_ptr<Person> pP2 = Change(pP); // error: unique_ptr 删除了拷贝构造,所以需要使用 move 关键字转移所有权 unique_ptr<Person> pP2 = Change(move(pP)); // pP = pP2; // error:unique_ptr 删除了 = 赋值构造 cout << "-------------" << endl; cout << pP2->getAge() << endl; cout << "-------------" << endl; if(pP == nullptr){ cout << "pP 变量已失效" << endl; } return 0; } 输出:...

February 22, 2022 · 1 min · Rick Cui

C++11 mutable 关键字

一、修饰类成员变量 此关键字只能应用于类的非静态和非常量数据成员,mutable 是为了让 const 对象的某些数据成员可以被修改。static 是类的成员,不属于对象,常对象和常函数只会限制类的成员变量修改,所以类的 static 数据成员不需要 mutable 修饰,在常对象和常函数中也能被修改。 class Person{ public: int getAge() const{ m_count++; s_count++; return m_age; } int getCount()const{ return m_count; } private: int m_age{20}; mutable int m_count{0}; public: static int s_count; }; int Person::s_count = 0; int main() { Person p; p.getAge(); p.getAge(); p.getAge(); cout << p.getCount() << endl; // 3 cout << p.s_count << endl; // 3 return 0; } 二、修饰匿名函数 表示可以修改按值传入的变量的副本(不是值本身),类似于不带 const 关键字的形参。使用 mutable 关键字后对按值传入的变量进行的修改,不会将改变传递到 Lambda 表达式之外。如果不加 mutable 关键字,按值传入的变量是只读的,即使在 Lambda 表达式内部也不可修改...

February 22, 2022 · 1 min · Rick Cui

C++11 auto 与 decltype 关键字

一、进行自动类型推导 auto 的自动类型推断发生在编译期,所以使用 auto 并不会造成程序运行时效率的降低。 而是否会造成编译期的时间消耗,我认为是不会的,在未使用 auto 时,编译器也需要得知右操作数的类型,再与左操作数的类型进行比较,检查是否可以发生相应的转化,是否需要进行隐式类型转换。 auto 属于类类型推导 decltype 是包含声明修饰符的声明类型推导 int main() { int a = 10; auto val = a; cout << typeid(val).name() << endl; // i return 0; } 二、在定义函数模板时,用于声明依赖模板参数的变量类型 不到编译的时候,x * y 的真正类型很难确定 template <class _Tx,class _Ty> void Multiply(_Tx x, _Ty y) { auto v = x * y; std::cout << v; } int main() { int a = 10; double b = 1....

February 22, 2022 · 3 min · Rick Cui

gdb 调试使用

一、生成带有调试信息的程序 gcc main.c -o app -g 二、启动调试 启动调试:gdb app 设置参数: set args set args 123 abc 456 ddd 查看代码: list 或 l 查看代码显示行数:show listsize 设置代码显示行数:set listsize 20 查看当前文件: l l 行号 l 函数名 查看非当前文件: l 文件名:行号 l 文件名:函数名 三、断点相关 设置断点: break 行号 b 行号 b 函数名 b 文件名:行号 b 文件名:函数名 查看断点:info break 或 i b 删除断点: del 断点Num d Num d Num1 Num2 d Num1-Num10 设置断点无效:dis Num 断点生效:ena Num 设置条件断点:b 行号 if i == 10 四、调试相关 启动运行: start - s run - r 退出 gdb 调试:quit - q 打印变量的值:p 变量名 打印变量的类型:ptype 变量名 向下单步调试: next - n step - s 跳出函数体:finish 从循环中跳出(循环体中不能有断点):until 设置变量的值:set var 变量名 = value 继续运行到下一个断点:continue - c 监视变量:display 变量名 查看所有的监视变量的信息:info(i) display 取消变量监视:undisplay Num

February 20, 2022 · 1 min · Rick Cui

Makefile 使用

一、make gcc 编译器 make 是 Linux 自带的构建器 二、文件命名 makefile Makefile 三、makefile 中的规则 例如:gcc a.c b.c c.c -o app 规则由三部分组成:目标、依赖、命令 app:a.c b.c c.c gcc a.c b.c c.c -o app makefile 中可以有多条规则 四、makefile 优化 版本一: app:main.c add.c sub.c gcc main.c add.c sub.c -I ./ -o app 存在的问题: 效率低,其中一个文件修改了,剩余的其它文件都要重新编译 版本二: app:main.o add.o sub.o gcc main.o add.o sub.o -I ./ -o app main....

February 19, 2022 · 1 min · Rick Cui