C++ 新特性auto

#include <iostream>
#include <vector>
#include <typeinfo>
#include <list>
/*
1.当不声明为指针或引用时,auto的推导结果和初始化表达式
抛弃引用和cv(const、volatile)限定符后类型一致;
2.当声明为指针或引用时,auto的推导结果将保持初始化表达式的csv属性;
3.不能用于函数的参数,必须被初始化,C++20可以了
4.不能用于非静态成员变量,非静态成员属于对象,对象创建的时候才会对非静态成员初始化,auto编译阶段进行类型推导,非静态成员变量编译时变量还没有进行初始化
5.不能使用auto定义数组和赋值
int arr[] = {1,2,3};//ok
auto arr1[]={1,2,3}; //error
auto arr2[]=arr; // error
auto arr3 = arr; // ok ,arr3=>int*
6.一般用于iterator迭代器类型声明
7.定义一个泛型函数func,多个类中都有
get()静态返回值函数,但返回类型不同,若想在
func中调用get函数并获取其返回值,需要使用auto进行
变量类型声明;
8.类的静态非常量成员变量也不可以修饰,static auto var1=0; //error
类的静态常量成员变量可以被auto修饰, static const auto var1=0;//ok, const变量被初始化,可以正常推导
9.无法使用auto推导模板类型
template<typename T>
struct Test{};
Test<int> t;
Test<auto> t1 = t; //error,auto不能推出模板类型
*/
void test1()
{
    std::vector<int> vec = {1, 2, 3, 4, 5};
    // 若不使用auto类型推导,则会写很长的冗余std::vector<int>::iterator
    for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it)
    {
        std::cout << *it << std::endl;
    }

    // 使用auto优化代码变得更简洁
    for (auto it = vec.begin(); it != vec.end(); ++it)
    {
        std::cout << *it << std::endl;
    }
}

// 1.当不声明为指针或引用时,auto的推导结果和初始化表达式
// 抛弃引用和cv(const、volatile)限定符后类型一致;

// 2.当声明为指针或引用时,auto的推导结果将保持初始化表达式的csv属性;
void test2()
{
    int x = 0;
    const auto e = x; // e->const int
    auto f = e;       // f->int,原因:当表达式带有const属性时,auto会把const属性抛弃掉,推导成non-const类型int;

    const auto &g = x;
    std::cout << typeid(g).name() << std::endl; // g->const int
    auto &h = g;                                //推导出h->const int&,当auto和引用结合时auto的推导将保留表达式的const属性;
}

// 在宏定义中应用,场景性能会提升
#define MAX1(a, b) (a) > (b) ? (a) : (b)
#define MAX2(a, b)             \
    {                          \
        auto _a = (a);         \
        auto _b = (b);         \
        _a > _b ? (_a) : (_b); \
    }
void test3()
{
    MAX1(1 + 2 + 3, 2 + 3 + 4); // a或b其中一个会经过两次计算
    MAX2(1 + 2 + 3, 2 + 3 + 4); // MAX2使用auto推导出结果进行比较,性能优
}

// auto声明的指针或引用变量不能指向或绑定一个临时对象
int Temp() { return 0; }
void test4()
{
    // auto *p = &Temp(); // error
    // auto &l = Temp();  // non-const引用不能指向一个临时变量
    auto &&r = Temp(); // 右值引用指向临时变量完全没问题,临时变量声明周期与r进行绑定
}

// auto与其他类型一样,可以一行定义多个变量(只有第一个类型被推导,推导出的数据类型用于其他变量),所以
// 不允许这些变量类型不相同,如果类型不相同编译报错,但不建议一行定义多个变量
void test4()
{

    auto a = 0, b = 1; // a and b all int
    // auto c = 1, d = 2.0f; // error
}
// auto不适用于数组定义和赋值
void test3()
{
    int array[] = {1, 2, 3, 4, 5};
    //     auto array[] = {1, 2, 3, 4, 4, 5}; // error, auto不能定义数组
    //     auto array1[] = array;             // error, auto不能用于数组赋值
}

// 不能用于函数参数和模板参数
void function(auto it)
{
    std::cout << it << std::endl;
}
template <typename T>
struct Test
{
    // auto不能用于类的静态非常量数据成员,静态const成员可以
    // static auto it; // error
    static const auto cit = 0;//ok,const 常量被初始化,可以正常推导
};

void test4()
{
    function(1);
    function("c++"); // c++20可以
    Test<int> t;
    // Test<auto> it = t; error, can not referred

    // 不能用于
}

// auto适用于泛型函数
struct A
{
    static int Do()
    {
        std::cout << "class A" << std::endl;
        return 0;
    }
};
struct B
{
    static std::string Do()
    {
        std::cout << "class B" << std::endl;
        return std::string("B");
    }
};

template <typename T>
void func()
{
    auto res = T::Do(); // auto虽然不能作为模板参数推导类型,但可以用于模板函数中变量声明
    std::cout << res << std::endl;
}
void test5()
{
    func<A>();
    func<B>();
}

// 若不使用auto关键字,但模板函数需要另一个参数用于指定返回值
template <typename T, typename R>
void funcNew()
{
    R res = T::Do();
    std::cout << res << std::endl;
}

void test6()
{
    funcNew<A, int>();
    funcNew<B, std::string>();
}

// auto 可以用于函数返回值类型推导(尾返回类型推导)
template<typename T1, typename T2, typename R>
R add1(T1 t1, T2 t2) {
    return t1+t2;
}
// 发现函数调用还要传递返回值类型,但有的情况不知道返回值类型就需要使用auto
// 但可能会想到使用decltype,但编译报错,从左到右编译时发现t1和t2尚未定义,因此c++11引入
// 尾返回类型

template<typename T1, typename T2>
decltype(t1+t2) add2(T1 t1, T2 t2) {
    return t1+t2;
}

// 尾返回类型decltype(t1+t2),结合auto一起使用(c++14可以去掉尾返回类型decltype)
template<typename T1, typename T2>
auto add2(T1 t1, T2 t2)->decltype(t1+t2) {
    return t1+t2;
}

// decltype(auto):用于对转发函数或封装的返回类型进行推导
std::string lookup1();
std::string& lookup2();

std::string  lookup_str() {
    return lookup1();
}
std::string& lookup_str_ref() {
    return lookup2();
}

decltype(auto) lookup_str1() {
    return lookup1();
}
decltype(auto) lookup_str_ref1() {
    return lookup2();
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值