天天看点

C++11--学习简记

auto类型推导的语法和规则

auto 要求必须对变量进行初始化

int  x = 0;
auto *p1 = &x;   //p1 为 int *,auto 推导为 int
auto  p2 = &x;   //p2 为 int*,auto 推导为 int*
auto &r1  = x;   //r1 为 int&,auto 推导为 int
auto r2 = r1;    //r2 为  int,auto 推导为 int
           

auto与const结合

int  x = 0;
const  auto n = x;  //n 为 const int ,auto 被推导为 int
auto f = n;      //f 为 const int,auto 被推导为 int(const 属性被抛弃)
const auto &r1 = x;  //r1 为 const int& 类型,auto 被推导为 int
auto &r2 = r1;  //r1 为 const int& 类型,auto 被推导为 const int 类型
           

最后我们来简单总结一下 auto 与 const 结合的用法:

当类型不为引用时,auto 的推导结果将不保留表达式的 const 属性;

当类型为引用时,auto 的推导结果将保留表达式的 const 属性。

auto 用于泛型编程

auto 的另一个应用就是当我们不知道变量是什么类型,或者不希望指明具体类型的时候,比如泛型编程中。我们接着看例子:

#include <iostream>
using namespace std;

class A{
public:
    static int get(void){
        return 100;
    }
};

class B{
public:
    static const char* get(void){
        return "http://c.biancheng.net/cplus/";
    }
};

template <typename T>
void func(void){
    auto val = T::get();
    cout << val << endl;
}

int main(void){
    func<A>();
    func<B>();
    return 0;
}
           

运行结果:

100
http://c.biancheng.net/cplus/
           

using定义别名(替代typedef)

C98

template <typename Val>
struct str_map
{
    typedef std::map<std::string, Val> type;
};
str_map<int>::type map1;
           

C++11

template <typename Val>
using str_map_t = std::map<std::string, Val>;
str_map_t<int> map1;
           
// 重定义unsigned int
typedef unsigned int uint_t;
using uint_t = unsigned int;
// 重定义std::map
typedef std::map<std::string, int> map_int_t;
using map_int_t = std::map<std::string, int>;
           

C++11 tuple元组详解

struct person{
	char *m_name;
	char *m_addr;
	int *m_ages;
};
//使用tuple来表示这样一个结构体,作用是一样的
std::tuple<const char *,const char *,int>
           

Lambda表达式

Lambda 表达式的 [] 用来确定捕获参数:

1.[=]:捕获的局部变量只可读不可写,捕获范围是当前 Lambda 表达式之前的作用域。

2.[&]:捕获的局部变量可读可写。

[ capture ] ( params ) opt -> ret { body; };

void MyClass::function() {
  // 使用 [this] 来捕获 this
  auto fun1 = [this](int v){cout << v + this->num << endl; };
  // 使用 [&] 捕获所有父作用域的引用,包括 this
  auto fun2 = [&](int v){cout << v + this->num << endl; };
}
int main(void) {
  int num = 100;
  // read only 
  auto fun1 = [=](){ cout << num << endl; };
  fun1();
  // read and write
  auto fun2 = [&num](){ num = 200; cout << num << endl; };
  fun2();
  // num = 200
  cout << num << endl;
  return 0;
}
---------------------------------------------------------------------------
//遍历
int main() {
  vector<int> vec = {1, 2, 3, 4, 5};
  // 定义 Lambda
  auto fun = [](int num){ cout << num << endl;}
  for_each(vec.begin(), vec.end(), fun);
  // 将 vec 中的元素都加 1,修改参数必须传递参数的引用
  for_each(vec.begin(), vec.end(), [](int& num){ num += 1;});
  for_each(vec.begin(), vec.end(), fun);
  return 0;
}
           
auto f = [](int a) -> int { return a + 1; };
std::cout << f(1) << std::endl;  // 输出: 2
           

for循环

//for循环遍历普通数组
    for (char ch : arc) {
        cout << ch;
    }
 //for循环遍历 vector 容器
   for (auto ch : myvector) {
       cout << ch;
   }
  //{}的使用
   for (int num : {1, 2, 3, 4, 5}) {
      cout << num << " ";
   }
  //for循环遍历并修改容器中各个字符的值
   for (auto &ch : myvector) {
       ch++;
   }    
           

右值引用

2 个 ‘&’ 表示右值引用。

int num = 10;
//int && a = num;  //右值引用不能初始化为左值
int && a = 10;
           

某些场景中,我们可能需要限制调用成员函数的对象的类型(左值还是右值)所谓引用限定符,就是在成员函数的后面添加 “&” 或者 “&&”,从而限制调用者的类型(左值还是右值)

#include <iostream>
using namespace std;

class demo {
public:
    demo(int num):num(num){}
    int get_num()&{
        return this->num;
    }
private:
    int num;
};
int main() {
    demo a(10);
    cout << a.get_num() << endl;          // 正确
    //cout << move(a).get_num() << endl;  // 错误
    return 0;
}
           

nullptr:初始化空指针

实际开发中,避免产生野指针最有效的方法,就是在定义指针的同时完成初始化操作,即便该指针的指向尚未明确,也要讲其初始化空指针。

int * a1 = nullptr;
char * a2 = nullptr;
double * a3 = nullptr;
           

shared_ptr智能指针

程序突然崩溃、程序运行所用内存越来越多最终不得不重启,往往都是内存资源管理不当造成。

1.有些资源已经被释放,但指向它的指针并没有改变指向(成了野指针),并且后续还在使用;

2.有些内存资源已经被释放,后期又试图在释放一次(重复释放统一内存会导致程序运行崩溃);

3.没有及时释放不在使用的内存资源,造成内存泄露,程序占用的内存资源越来越多。

std::shared_ptr<int> p1;             //不传入任何实参
std::shared_ptr<int> p2(nullptr);    //传入空指针 nullptr
std::shared_ptr<int> p3(new int(10));
std::shared_ptr<int> p3 = std::make_shared<int>(10);
//调用拷贝构造函数
std::shared_ptr<int> p4(p3);//或者 std::shared_ptr<int> p4 = p3;
//调用移动构造函数
std::shared_ptr<int> p5(std::move(p4)); //或者 std::shared_ptr<int> p5 = std::move(p4);
           

unique_ptr

unique_ptr<string> p3(new string("auto"));
unique_ptr<string> p4;
p4=p3;//此时会报错
           

继续阅读