C++11特性小结之decltype、类内初始化、列表初始化返回值

作用:返回表达式或变量的类型

返回值规则:

  • 若e是一个左值(lvalue,即“可寻址值”),则decltype(e)将返回T&
  • 若e是一个临终值(xvalue),则返回值为T&&
  • 若e是一个纯右值(prvalue),则返回值为T

decltype()不会执行括号内的表达式,decltype返回的类型是用于声明的,不能用于单纯的判断。比如decltype(a)==int,是不可以的,只能是在定义新的变量、返回值的地方使用:

int a=1;
decltype(a) b (等价于int b)

若是给变量加多了1个括号,则会成为一个表达式。

int a = 1;
int b=2;
decltype((a)) d=b // decltype((a))
返回类型int&。而引用必须赋初值,所以这里的d必须赋初值。

若表达式和指针相关的用法:

设p是指向int变量的指针

  1. decltype(*p)-》返回int& 即引用
  2. decltype(p)-》返回int* 即指针
  3. decltype(&p)-》返回int** 即指针的指针。

这里解释一下为什么1返回的是引用而不是int:因为*p返回的本质上就是一个引用,当我们向*p赋值的时候,改变的是变量原本的值,而不是做了一个拷贝,显然这是引用的性质。

泛型编程中使用decltype:

通过和尾置返回类型结合,可以使得返回值可以由编译器推断,无需程序员指出。主要用于编写转发函数

int& foo(int& i);
float foo(float& f);

template <class T>
auto transparent_forwarder(T& t) −> decltype(foo(t))
{
 return foo(t);
}

像这个例子如果没有decltype,我们无法确定foo(t)到底是两个备选函数中的哪一个,因为这是在运行时决定的。这样子我们无法直接编写transparent_forwarder函数的返回值。

还有其他很多例子,decltype常用于难以确定变量类型的地方,而模板就是为了适配多类型而产生的,所以在泛型编程中,很多时候都会用到decltype来做到灵活定义变量类型。

类内初始化

C++11以前是不可以在一个类的数据成员声明的时候初始化的,除非是一个const的静态变量:

class A
{
 static int i = 1; //correct,不得不在此赋值,因为const常量必须在声明时赋值
 int num=2; //error,不允许在类内声明的时候对数据成员初始化
};

这样子带来繁琐的问题就是:尽管我们只是想为所有该类的实例的数据成员都设置一个初始值,也必须自己定义一个构造函数才能做到。

于是在c++11:允许直接在类内初始化值(前提:这个值必须是常量表达式)。

顺序:类内部初始化先于构造函数初始化进行,构造函数初始化会覆盖类内部初始化。也就是说,如果我们即定义了类内初始化值,又定义了自己的构造函数,最终的结果还是按照我们的意愿,对数据成员按照构造函数赋值。

使用方法:

class A
{
 int num=2; //correct,C++11允许在类内声明的时候对数据成员初始化
 int a{7} //用花括号赋值也可以,a=7
};

注意:C++11中,仍然没有改变静态数据成员必须在类内声明,类外初始化的事实。

class A
{
 static int d = 1; //error
};
int A::d = 1 //correct,一般来说:初始化语句会放在cpp文件,类定义放在h文件

列表初始化返回值

在C++11之前,如果我们想要返回一组数据,我们必须在子函数中构造一个对应的容器,借助容器来进行返回。

vector<int> process()
{
 vector<int> v={1,2,3,4}
 return v;
}

在新标准下,我们可以直接返回字面值,该字面值会用于容器的构造,而无需我们自己去构造。

vector<int> process()
{
 return {1,2,3,4};
}

总结

到此这篇关于C++11特性小结之decltype、类内初始化、列表初始化返回值的文章就介绍到这了,更多相关C++11特性decltype、类内初始化、列表初始化返回值内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 简述C++11就地初始化与列表初始化

    1.就地初始化 1.1简介 在C++11之前,只能对结构体或类的静态常量成员进行就地初始化,其他的不行. class C { private: static const int a=10; //yes int a=10; //no } 在C++11中,结构体或类的数据成员在申明时可以直接赋予一个默认值,初始化的方式有两种,一是使用等号"=",二是使用大括号列表初始化的方式.注意,使用参考如下代码: class C { private: int a=7; //C++11 only int

  • C++中各种初始化方式示例详解

    前言 本文主要给大家介绍了关于C++初始化方式的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. C++小实验测试:下面程序中main函数里a.a和b.b的输出值是多少? #include <iostream> struct foo { foo() = default; int a; }; struct bar { bar(); int b; }; bar::bar() = default; int main() { foo a{}; bar b{}; std::co

  • C++ 11新特性之大括号初始化详解

    本文主要给大家介绍了关于C++11新特性之大括号初始化的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: C++11之前,C++主要有以下几种初始化方式: //小括号初始化 string str("hello"); //等号初始化 string str="hello"; //大括号初始化 struct Studnet{ char* name; int age; }; Studnet s={"dablelv",18}; //

  • C++中静态初始化数组与动态初始化数组详解

    静态初始化的数组的长度必须是在程序中确定的常数,不能是由用户输入的变量 例子: int a[10];//正确 Student stud[10];//正确:Student是一个学生类 int n;cin>>n;int a[n];//错误 int n;cin>>n;Student stud[n];//错误:Student是一个学生类 动态初始化数组可以使用用户输入的变量作为数组的长度. 例子: int n; cin>>n; int *a=new int[n];//这样整数数

  • 关于C++11的统一初始化语法示例详解

    前言 本文主要给大家介绍了C++11统一初始化语法的相关内容,关于在当前新标准C++11的语法看来,变量合法的初始化器有如下形式: X a1 {v}; X a2 = {v}; X a3 = v; X a4(v); 其实,上面第一种和第二种初始化方式在本质上没有任何差别,添加=则是一种习惯上的行为.使用花括号进行的列表初始化语法,其实早在C++98时代就有了,只不过历史上他们只是被用来对数组元素进行初始化操作,以及初始化自定义POD类型的数据(简单理解就是可以memcpy复制对象的类型).比如:

  • C++使用初始化列表的方式来初始化字段的方法

    几个月之前,接触Android recovery源代码的时候,看ScreenRecoveryUI类的时候,那时候C++基础还不是特别好,一直不明白以下的初始化方式: 下面这个是Recovery的一个构造函数,代码位于:screen_ui.cpp,它的类的实现在screen_ui.h. 如下这个ScreenRecoveryUI类,这个类是继承于RecoveryUI类的: 这个文件在screen_ui.h class ScreenRecoveryUI : public RecoveryUI { pu

  • C++常量详解一(常量指针与常量引用的初始化)

    1.常量 1.1.常量的初始化: const对象一旦创建后其值就不能再改变,所以const对象必须初始化.这里我们要注意一点,像const int *p和const int &r都并不是const对象.因为const int *p只是表示不能通过p改变p所指的对象的值,p的值是可以变的,所以p可以不用初始化.至于r ,引用本身就不是对象,所以r也并不是const对象,r之所以一定初始化,是因为引用必须初始化.对于以上内容,你也可以理解为底层const 修饰的并不是const对象,还要注意像con

  • 解决C++全局变量只能初始化不能赋值的问题

    C++中,全局变量只能声明.初始化,而不能赋值 也就是说,下面这样是不被允许的: #include <cstdio> using namespace std; int a; a = 2; int main() { return 0; } 错误提示是: C++ requires a type specifier for all declarations 声明.初始化与赋值的区别: 声明:int a; 初始化:int a = 2;(在声明的时候顺带赋值叫做初始化) 赋值:a = 2; 只有定义(i

  • C++11特性小结之decltype、类内初始化、列表初始化返回值

    作用:返回表达式或变量的类型 返回值规则: 若e是一个左值(lvalue,即"可寻址值"),则decltype(e)将返回T& 若e是一个临终值(xvalue),则返回值为T&& 若e是一个纯右值(prvalue),则返回值为T decltype()不会执行括号内的表达式,decltype返回的类型是用于声明的,不能用于单纯的判断.比如decltype(a)==int,是不可以的,只能是在定义新的变量.返回值的地方使用: int a=1; decltype(a)

  • C++11新特性之列表初始化的具体使用

    目录 统一的初始化方法 列表初始化的一些使用细节 初始化列表 1.任何长度的初始化列表 2.std::initialzer-list的使用细节 列表初始化防止类型收窄 在我们实际编程中,我们经常会碰到变量初始化的问题,对于不同的变量初始化的手段多种多样,比如说对于一个数组我们可以使用 int arr[] = {1,2,3}的方式初始化,又比如对于一个简单的结构体: struct A { int x; int y; }a={1,2}; 这些不同的初始化方法都有各自的适用范围和作用,且对于类来说不能

  • C++11中列表初始化机制的概念与实例详解

    目录 概述 实现机制详解 POD类型的列表初始化 含有构造函数的类的列表初始化(C++11) 列表初始化用于函数返回值 引入std::initializer_list 代码验证 应用 列表初始化防止类型收窄 总结 概述 定义:列表初始化是C++11引入的新标准,目的是统一初始化方式 C++11以前只能使用列表初始化来初始化内置类型数组和POD类型对象,C++11中列表初始化可以用于初始化任何类型对象 POD(plain old data)类型:仅由内置类型变量构成且不含指针的类,简单来说是可以直

  • C++11中初始化列表initializer lists的使用方法

    C++11引入了初始化列表来初始化变量和对象.自定义类型,如果想用初始化列表就要包含initializer_list头文件. C++11将使用大括号的初始化(列表初始化)作为一种通用初始化方式,可用于所有类型.初始化列表不会进行隐式转换. C++11提供的新类型,定义在<initializer_list>头文件中. template< class T > class initializer_list; 先说它的用处吧,然后再详细介绍一下. 首先有了initializer_list之

  • C++类与对象深入之运算符重载与const及初始化列表详解

    目录 一:运算符重载 相等运算符重载 赋值运算符重载 小于运算符重载 二:const成员 const修饰类的成员函数 三:cin.cout重载 四:初始化列表 构造函数赋初值 初始化列表 explicit关键字 一:运算符重载 C++为了增强代码的可读性引入了运算符的重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型以及参数列表,其返回值类型与参数列表与普通函数类似. 函数名字为:关键字operator后面接需要重载的运算符符号 函数原型:返回值类型 operator操作符(参数列表)

  • C++类的返回值是*this的成员函数问题

    目录 C++类返回值是*this成员函数 1 返回值是左值 2 const成员函数的返回值 对C++类成员返回语句return *this的理解 C++类返回值是*this成员函数 当C++类的成员函数其返回值是*this时,表示返回值是调用该成员函数的变量的引用. 例如: class A { public:   A& func1() {   return *this;   }   int i{0}; } 此时,类A的成员函数func1的返回值是*this,该成员函数的返回值类型是A&.

  • C++第11版本中的一些强大的新特性小结

    Auto Type Deduction 自动类型推导 auto 关键字让用户得以使用 C++ 内置的类型推导特性. std::string something = somethingthatreturnsastring.getString(); auto something = somethingthatreturnsastring.getString(); Auto 关键字会对上述自变量(something)进行自动推导,得出其应该是 string 类型的结论,并在 auto 出现的地方用正确

  • 你应该知道的Python3.6、3.7、3.8新特性小结

    很多人在学习了基本的Python语言知识后,就转入应用阶段了,后期很少对语言本身的新变化.新内容进行跟踪学习和知识更新,甚至连已经发布了好几年的Python3.6的新特性都缺乏了解. 本文列举了Python3.6.3.7.3.8三个版本的新特性,学习它们有助于提高对Python的了解,跟上最新的潮流. 一.Python3.6新特性 1.新的格式化字符串方式 新的格式化字符串方式,即在普通字符串前添加 f 或 F 前缀,其效果类似于str.format().比如 name = "red"

  • IntelliJ IDEA2020.3 新特性(小结)

    北京时间2020年12月1日,JetBrain公司推出了二十周年第三个稳定版的IntelliJ IDEA 2020.3 . 距离上一个稳定版IDEA,过去了小五个月,这次的更新来得比较晚,我的博客也是.如果不是同事提醒,我也差点忘记了自己其实是打算把IDEA编辑器这个系列给一直更新下去的哈哈哈,话不多说,让我们先进官网看看. 以下是官网的原话: IntelliJ IDEA 2020.3 adds interactive hints and inline watches in the debugg

  • C++ 静态成员的类内初始化详解及实例代码

    C++ 静态成员的类内初始化详解及实例代码 一般来说,关于C++类静态成员的初始化,并不会让人感到难以理解,但是提到C++ 静态成员的"类内初始化"那就容易迷糊了. 我们来看如下代码: //example.h #include<iostream> #include<vector> using namespace std; class Example{ public: static double rate = 6.5; static const int vecSi

随机推荐