C++学习3
基础理论
讲右值、移动比较清楚容易入门的一篇文档
参考:https://zhuanlan.zhihu.com/p/606580366
左值:可以取地址的、有名字的值就是左值,左值可以放到赋值语句的左边(没有被const限定的情况下)。
右值:不能够取地址、没有名字的值就是右值。右值不能用&获取内存地址,而且生命周期短(只在定义的这一行语句内有效),在构造、使用后立刻就释放了。
左值引用:左值引用能绑定左值,但不能直接绑定右值,只有const的左值引用才可以绑定右值,不能修改。
std::string& r = std::string{
"Hello"}; //error: non-const lvalue reference to type xxx
const std::string& cr = std::string{
"Hello"}; // ok
右值引用:右值引用的定义方式为type&& r。右值引用可以直接绑定右值,但不能绑定左值。
std::string&& r = std::string{
"Hello"}; // ok
std::string s{
"hello"};
std::string&& rs = s; //error: rvalue reference to type 'basic_string<...>' cannot bind to lvalue of type 'basic_string<...>'
入参为左值的函数类型:
template<typename T>
void func(T& param) {
cout << param << endl;
}
入参为右值的函数类型定义:
template<typename T>
void func(T&& param) {
cout << param << endl;
}
右值引用本身是个左值:
std::move的入参是个左值!
大神的无敌总结如下:
C++11中的default函数
https://blog.csdn.net/u013318019/article/details/113894153
对于C++ 11标准中支持的default函数,编译器会为其自动生成默认的函数定义体,从而获得更高的代码执行效率(比用户自定义的代码效率更高,哪怕是相同的空函数),也可免除程序员手动定义该函数的工作量。详细内容参考上面链接。
C++ override
https://blog.csdn.net/qq_41540355/article/details/120751543
(1) 这个关键字一般是加在子类中的;
(2) 主要目的是为了在子类(派生类)中提醒父类(基类)中被继承的虚函数必须要加上virtual关键字,否则没有被override的同名对象就会报编译失败。
(3) 设计virtual的目的是为了提醒编译器析构时除了析构父类,还要析构子类,防止内存泄露;
std::uniquer_ptr用法
参考:https://en.cppreference.com/w/cpp/memory/unique_ptr
常用用法:
std::unique_ptr<int> ptr = std::make_unique<int>(10);
std::cout << *ptr << std::endl; // 打印10
{
std::unique_ptr<int[]> p(new int[3]);
} // 析构时会自动释放所有三个new出来的int类型的指针数据;
std::make_unique会自己去系统申请内存,并且利用传入的数据(10)作为原始的构造参数;
std::make_unique可以自定义析构函数,由RAII帮助我们自动调用该析构函数:
std::ofstream("demo.txt") << 'x'; // prepare the file to read
{
using unique_file_t = std::unique_ptr<std::FILE, decltype(&close_file)>;
unique_file_t fp(std::fopen("demo.txt", "r"), &close_file);
if (fp)
std::cout << char(std::fgetc(fp.get())) << '\n';
} // `close_file()` called here (if `fp` is not null)
全部完整用例如下:
#include <cassert>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <memory>
#include <stdexcept>
// helper class for runtime polymorphism demo below
struct B
{
virtual ~B() = default;
virtual void bar() {
std::cout << "B::bar\n"; }
};
struct D : B
{
D() {
std::cout << "D::D\n"; }
~D() {
std::cout << "D::~D\n"; }
void bar() override {
std::cout << "D::bar\n"; }
};
// a function consuming a unique_ptr can take it by value or by rvalue reference
std::unique_ptr<D> pass_through(std