码迷,mamicode.com
首页 > 编程语言 > 详细

C++关键字

时间:2018-09-20 14:15:16      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:其它   完成   修改   运行   union   就是   顺序   sizeof   declared   

auto

用法

1.变量声明时根据初始化表达式自动推断该变量的类。

2.声明函数时作为函数返回值的占位符

自动类型推断

使用auto关键字从初始化表达式中推断出变量的数据类型,如声明vector类型变量的迭代器需要这样声明vector::iterator iter,使用auto可以简化为auto iter。另外,在模板函数定义时,如果变量的类型依赖于模板参数,我们难以确定变量的类型,可以使用auto关键字让编译器确定变量类型

#include <iostream>
#include <vector>
using namespace std;

template<class T, class U>
void add(T t, U u)
{
    auto s = t + u;
    cout << "type of t + u is " << typeid(s).name() << endl;
}

int main()
{
    // 简单自动类型推断
    auto a = 123;
    cout << "type of a is " << typeid(a).name() << endl;
    auto s("fred");
    cout << "type of s is " << typeid(s).name() << endl;

    // 冗长的类型说明(如迭代器)
    vector<int> vec;
    auto iter = vec.begin();
    cout << "type of iter is " << typeid(iter).name() << endl;

    // 使用模板技术时,如果某个变量的类型依赖于模板参数,使用auto确定变量类型
    add(101, 1.1);
}

函数返回值占位符

auto与decltype关键字配合使用,作为返回值类型后置时的占位符。此时auto关键字不表示自动类型检测,仅仅是表示后置返回值的语法的一部分。

template<class T, class U>
auto add(T t, U u) -> decltype(t + u) 
{
    return t + u;
}

Attention

1.使用auto关键字的变量必须有初始值。

2.可以使用volatile,*(指针类型),&(引用类型),&&(右值引用)来修饰auto关键字。

auto a = 10;
auto *pa = new auto(a);
auto **rpa = new auto(&a);
cout << typeid(a).name() << endl;   // 输出: int
cout << typeid(pa).name() << endl;  // 输出: int *
cout << typeid(rpa).name() << endl; // 输出: int **

3.函数参数和模板参数不能被声明为auto

4.使用auto关键字声明变量的类型,不能自动推导出顶层的CV-qualifiers和引用类型,除非显示声明。例如:

使用auto关键字进行类型推导时,如果初始化表达式是引用类型,编译器会去除引用,除非显示声明。

    int i = 10;
    int &r = i;
    auto a = r;
    a = 13; // 重新赋值
    cout << "i = " << i << " a = " << a << endl;    // 输出i=10,a=13

    // 显式声明
    auto &b = r;
    b = 15; // 重新赋值
    cout << "i = " << i << " b = " << b << endl;    // 输出i=15,a=15

使用auto使用auto关键字进行类型推导时,编译器会自动忽略顶层const,除非显示声明。

    const int c1 = 10;
    auto c2 = c1;
    c1 = 11; // 报错,c1为const int类型,无法修改const变量
    c2 = 14; // 正确,c2为int类型

    // 显示声明
    const auto c3 = c1;
    c3 = 15; // 报错,c3为const int类型,无法修改const变量

5.对于数组类型,auto关键字会推导为指针类型,除非被声明为引用。例如:

    int a[10];
    auto b = a;
    cout << typeid(b).name() << endl;   // 输出:int *

    auto &c = a;
    cout << typeid(c).name() << endl;   // 输出:int [10]

decltype

decltype简介

我们之前使用的typeid运算符来查询一个变量的类型,这种类型查询在运行时进行。RTTI机制为每一个类型产生一个type_info类型的数据,而typeid查询返回的变量相应type_info数据,通过name成员函数返回类型的名称。同时在C++11中typeid还提供了hash_code这个成员函数,用于返回类型的唯一哈希值。RTTI会导致运行时效率降低,且在泛型编程中,我们更需要的是编译时就要确定类型,RTTI并无法满足这样的要求。编译时类型推导的出现正是为了泛型编程,在非泛型编程中,我们的类型都是确定的,根本不需要再进行推导。

而编译时类型推导,除了auto关键字,还有decltype。

decltype与auto关键字一样,用于进行编译时类型推导,不过它与auto还是有一些区别的。decltype的类型推导并不是像auto一样是从变量声明的初始化表达式获得变量的类型,而是总是以一个普通表达式作为参数,返回该表达式的类型,而且decltype并不会对表达式进行求值。

decltype用法

推导出表达式类型

    int i = 4;
    decltype(i) a; //推导结果为int。a的类型为int。

与using/typedef合用,用于定义类型

    using size_t = decltype(sizeof(0));//sizeof(a)的返回值为size_t类型
    using ptrdiff_t = decltype((int*)0 - (int*)0);
    using nullptr_t = decltype(nullptr);
    vector<int >vec;
    typedef decltype(vec.begin()) vectype;
    for (vectype i = vec.begin(); i != vec.end(); i++)
    {
        //...
    }

重用匿名类型

在C++中,有时会遇上匿名类型,如:

    struct 
    {
        int d ;
        doubel b;
    }anon_s;

借助decltype,可以重新使用这个匿名的结构体:

    decltype(anno_s) as;//定义了一个上面的结构体

泛型编程中结合auto,用于追踪函数的返回值类型

    template <typename _Tx, typename _Ty>
    auto multiply(_Tx x, _Ty y)->decltype(_Tx*_Ty)
    {
        return x*y;
    }

static

static用法

1.函数内部声明的static变量,可作为对象间的一种通信机制

如果一局部变量被声明为static,那么将只有唯一的一个静态分配的对象,它被用于在该函数的所有调用中表示这个变量。这个对象将只在执行线程第一次到达它的定义使初始化。

局部静态对象

对于局部静态对象,构造函数是在控制线程第一次通过该对象的定义时调用。在程序结束时,局部静态对象的析构函数将按照他们被构造的相反顺序逐一调用,没有规定确切时间。

静态成员和静态成员函数

如果一个变量是类的一部分,但却不是该类的各个对象的一部分,它就被成为是一个static静态成员。一个static成员只有唯一的一份副本,而不像常规的非static成员那样在每个对象里各有一份副本。同理,一个需要访问类成员,而不需要针对特定对象去调用的函数,也被称为一个static成员函数。

static作用

隐藏

同时编译多个源文件时,所有未加static的全局变量和函数都具有全局可见性。如编译a.c和main.c:

//a.c
char a = ‘A‘; // global variable

void msg() { printf("Hello\n"); }
//main.c
int main(void) { 

    extern char a; // extern variable must be declared before use

    printf("%c ", a);

    (void)msg();

    return 0;  
}

程序的运行结果为A Hello

如果加了static,就会对其它源文件隐藏。例如在a和msg的定义前加上static,main.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏,而对于变量,static还有下面两个作用。

保持变量内容的持久

存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。

默认初始化为0.其实全局变量也具备这一属性,因为全局变量也存储在静态数据区

在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置0,然后把不是0的几个元素赋值。如果定义成静态的,就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加‘\0’太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是‘\0’。

const

struct

union

enum

C++关键字

标签:其它   完成   修改   运行   union   就是   顺序   sizeof   declared   

原文地址:https://www.cnblogs.com/Apotato/p/9508129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!