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

2022-02-14 杂记

NULL,0,'\0',‘0’ int main() { char arr[] = {0, '\0', '0', 48}; printf("%c\n", arr[0]); printf("%c\n", arr[1]); printf("%c\n", arr[2]); printf("%c\n", arr[3]); printf("---------------\n"); printf("%d\n", arr[0]); printf("%d\n", arr[1]); printf("%d\n", arr[2]); printf("%d\n", arr[3]); return 0; } 输出: 0 0 --------------- 0 0 48 48 UTF-8 向下兼容 ASCII 编码,UTF-8 编码中,一个英文字为一个字节,一个中文一般为三个字节(ASCII、Unicode、UTF-8) 0xxxxxxx:单字节编码形式,这和 ASCII 编码完全一样,因此 UTF-8 是兼容 ASCII 的; 110xxxxx 10xxxxxx:双字节编码形式; 1110xxxx 10xxxxxx 10xxxxxx:三字节编码形式; 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字节编码形式; UTF-8:每字 1 ~ 6 字节 Unicode(UCS-2):每字都是 2 bytes UTF-16:每字 2 ~ 4 字节 UTF-32(UCS-4):每字都是 4 bytes float 单精度,浮点数在内存中是按科学计数法来存储的,小数点后6位能确定表示,float 是由 1 bit 符号位,8 bit 指数位和 23 bit 尾数位组成,精度是由尾数位决定的(2^23 = 8388608)...

February 15, 2022 · 1 min · Rick Cui

递归与递归树

逆序打印字符串 void printReverseString(const char* str){ if(*str == '\0'){ return; } printReverseString(str + 1); printf("%c", *str); } int main() { const char* str = "Hello World"; printReverseString(str); // dlroW olleH return 0; } 逆序输出链表 struct LinkNode{ int data; struct LinkNode* next; }; void printReverseLinkNode(struct LinkNode* header){ if(header == NULL){ return; } printReverseLinkNode(header->next); printf("%d\n", header->data); } int main() { struct LinkNode* header = malloc(sizeof(struct LinkNode)); struct LinkNode* node1 = malloc(sizeof(struct LinkNode)); node1->data = 10; node1->next = NULL; struct LinkNode* node2 = malloc(sizeof(struct LinkNode)); node2->data = 20; node2->next = NULL; struct LinkNode* node3 = malloc(sizeof(struct LinkNode)); node3->data = 30; node3->next = NULL; header->next = node1; node1->next = node2; node2->next = node3; printReverseLinkNode(header->next); return 0; } 递归实现给出一个数 8793,依次打印千位数 8、百位数 7、十位数 9、个位数 3...

February 7, 2022 · 2 min · Rick Cui