9159.com:int相同(除了布尔型和扩展字类型(例如

作者: 编程  发布:2019-08-28

C 学习笔记(一些新特性总结 1)

2.1 算术类型

空指针

nullptr 空指针的字面值常量,它的类型是std::nullptr_t(定义位于cstddef)

Tips for C Primer Charpter 1,primercharpter

C 学习笔记(一些新特性总结 1)

虽然我也用了 C 有挺多年了,但是一直本着够用就行的原则,没有特别深入的学习过C 的语法,所以好多高级的 C 特性都不了解。正好最近从网上找到了本书《C 14 Quick Syntax Reference》,挺薄的一本书,只有 100多页,但是覆盖了基本所有 C 的特性。这个小短文就是我看这本书时摘抄下来的一些我以前没有注意到的知识点。

文中所有代码都在 gcc version 5.3.0 (Rev1, Built by MSYS2 project) 上测试通过。

bool
char          character                        8
wchar_t        wide character                16
char16_t      Unicode character           16
char32_t      Unicode character           32
short          short integer                  16
int          integer                          16
long         long integer                   32
long long                                        64
float          single-precision floating-point    6 significant digits
double          double-precision floating-point    10 significant digits
long double     extended-precision floating-point 10 significant digits

自动类型推断

auto关键字,由auto定义的变量必须初始化。

第2章 变量和基本类型

基本内置类型:算数类型和空类型;算数类型又包括整型(字符和布尔类型也包括在内)和浮点型。

 

可寻址的最小内存块称为“字节”(byte),存储的基本单元称为“字(word)”;一个字通常由几个字节组成。

1字节(byte)=8比特(bit),比特非0即1。

 

类型unsigned int可以缩写为unsigned。

 

int与singed int相同(除了布尔型和扩展字类型(例如宽字符wchat_t)之外,其他的整型类型(例如short、long)也类似),但字符型例外,字符型有char、unsigned char、signed char三种类型,但char与signed char不相同;字符的表现形式只有两种:带符号的和无符号的,char实际上会表现为上述两者的其中一种,具体由编译器决定。

 

在算数表达式中不要使用char或bool。因为char在一些机器上可能是有符号的,而在另外的机器上可能是无符号的,使用char进行运算可能出错;如果硬要使用一个不大的整数,那么明确指定它为unsigned char或signed char。bool取值非0即1,不适宜用于算数表达式。

 

当赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值的总数取模后的余数。

例如:unsigned char占8个比特(1个字节),可以表示[0, 255]的共256个数值,当赋予区间外的一个值,假设是-1,则实际结果是(-1) % 256 = 255。

 

当赋给一个带符号类型一个超出它表示范围的值时,结果是未定义的,此时程序可能继续工作、崩溃或产生垃圾数据。

 

当一个算数表达式中既有无符号数又有int值时,那个int值会转换成无符号数。把int转换成无符号数的过程相当于把int赋给无符号类型。

切勿混用带符号类型和无符号类型。如果表达式既有带符号类型又有无符号类型,当带符号类型取值为负时会出现异常结果,这是因为带符号数会自动转换成无符号数。

例如:当a=-1,b=1,c=a*b,若a、b都是int,则c为-1;若a是int,b是unsigned int,则c的结果是(-1)%(2^32) * 1 = 4294967295(视当前机器上int所占bit数而定,这里假设int是32bit)。

 

整型字面值可写作十进制数、八进制数、十六进制数的形式。

0开头:八进制

0x、0X开头:十六进制

 

浮点数字面值可省略整数部分或小数部分。

例如:0.、.001

浮点数字面值默认是一个double。

 

可以以前缀或后缀指定字面值类型。

前缀

  u:char16_t(Unicode16字符)

  U:char32_t(Unicode32字符)

  L:wchar_t(宽字符)

  u8:char(UTF-8、仅用于字符串字面常量)

后缀

对整型字面值:

  u、U:unsigned

  l、L:long

  ll、LL:long long

对浮点型字面值:

  f、F:float

  l、L:long double

 

初始化与赋值是不同的概念。

初始化:创建变量时赋予其一个初始值

赋值:把对象的当前值擦除,并以一个新值替代

所以赋值的开销大于初始化

 

如果内置类型的变量未被显式初始化,它的值由定义的位置决定。

定义在任何函数体外:被初始化为0

定义在函数体内:将不被初始化,其值未定义

注:指针类型并非基本内置类型,但也有上述特性。

 

如果类的对象没有显示初始化,其值由类确定。(类的默认构造函数)

 

声明使得名字为程序所知,而定义创建与名字关联的实体。

如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而不要显式地初始化变量。

例如:

extern int i; //声明i而非定义i

int j; //声明并定义j

 

包含显式初始化的声明即成为定义。

extern double pi = 3.14; //定义;允许在函数体外这么做,但extern关键字的存在就没意义了

不允许在函数体内部初始化一个由extern关键字标记的变量。

 

引用本身并非对象,也没有实际的地址(若尝试用取地址符&取得某个“引用的地址”,实际取得的是所引用的对象的地址),它只是已存在的对象的别名。无法定义引用的引用,也无法定义指向引用的指针。

引用必须初始化,因为无法令引用重新绑定到另一对象。

所有引用的类型都要和与之绑定的对象严格匹配(有两个情况例外,将在后面提到)。

 

引用必须绑定到对象上,不能绑定到字面值或某个表达式的计算结果。

 

指针本身是一个对象,允许对指针赋值和拷贝,指针在其生命周期内可以指向不同对象。

指针无需在定义时赋初值。和基本内置类型相同,定义在所有函数体外的指针若未初始化,将有默认初值0,而块作用域内定义的指针将拥有一个不确定的值。

所有指针的类型都要和所指的对象严格匹配(有两个情况例外,将在后面提到)。

 

&、*出现在声明语句中,用来组成复合类型;&出现在表达式中,是一个取地址符;*出现在表达式中,是一个解引用符(或乘法运算符)。

 

nullptr = NULL = 0

 

void*是一种特殊的指针类型,可用于存放任意对象的地址。但不能直接操作void*指针所指的对象,因为对象的类型决定了能对对象所做的操作,而我们并不知道对象的类型。

 

指向指针的指针

指针是内存中的对象,像其它对象一样也有自己的地址,因此允许把指针的地址再存放到另一个指针当中。

通过*的个数区分指针的级别。**是指向指针的指针,***是指向指针的指针的指针,等等。

int i = 1024;

int *pi = &i; //pi指向一个int型的数

int *ppi = π //ppi指向一个int型的指针

9159.com 1

解引用int型指针会得到一个int型的数,解引用一个指向指针的指针会得到一个指针。

这里有三种方式取得i的值:i、*pi、**ppi。

 

for C Primer Charpter 1,primercharpter 第2章 变量和基本类型 基本内置类型:算数类型和空类型;算数类型又包括整型(字符和布尔类型也包...

16进制、8进制、2进制表示

int myOct = 062;
int myHex = 0x32;
int myBin = 0b00110010;

其中 16进制、8进制表示法是很早就支持的特性。2进制表示是 C 14 才正式支持的。
除此之外,C 14 还引入了单引号作为数字表示的分隔符。方便我们阅读很长的数字。比如下面这个例子:

int longBin = 0b1010'0101'1010'0101;

加了三个单引号作为分割,读起来就方便多了。

char_t类型保证机器最大扩展字符集中任意字符都可以存储

统一初始化和初始化列表

C 11 introduced the concept of uniform initialization, which means that for any initialization, you can use one common syntax. This syntax uses braces, so the following is possible now:

int values[] { 1, 2, 3 };

std::vectorv { 2, 3, 5, 7, 11, 13, 17 };

std::vectorcities {"Berlin", "New York", "London", "Braunschweig", "Cairo", "Cologne"};

std::complexc{4.0,3.0}; // equivalent to c(4.0,3.0)

使用初始化列表初始化时,不提供初始值时默认值初始化(0或nullptr),其他初始化方式若为提供初始值则值是未定义的。

int i; // i has undefined value

int j{}; // j is initialized by 0

int* p; // p has undefined value

int* q{}; // q is initialized by nullptr

使用初始化列表初始化时,若提供的值会将会损失精度时,编译器报错。

int x1(5.3); // OK, but OUCH: x1 becomes 5

int x2 = 5.3; // OK, but OUCH: x2 becomes 5

int x3{5.0}; // ERROR: narrowing

int x4 = {5.3}; // ERROR: narrowing

char c1{7}; // OK: even though 7 is an int, this is not narrowing

char c2{99999}; // ERROR: narrowing (if 99999 doesn’t fit into a char)

std::vector<int>v1 { 1, 2, 4, 5 }; // OK

std::vector<int>v2 { 1, 2.3, 4, 5.6 }; // ERROR: narrowing doubles to ints

std::initializer_list<>使得函数支持传入多值(通过初始值列表)

void print (std::initializer_list<int> vals){

           for (auto p=vals.begin(); p!=vals.end(); p) { 

                    std::cout << *p << "n";

                    }

}

print ({12,3,5,7,11,13,17}); // pass a list of values to print()

NULL 指针(nullptr)

早期的 C 中,我们用 0 或者 NULL 来表示无效的指针地址。C 11 专门引入了一个新的关键字 nullptr 来表示 NULL 指针。

int* p = nullptr; // ok

并且 nullptr 还是有类型的,类型为 nullptr_t:

nullptr_t mynull = nullptr; // ok

char16_t和char32_t为unicode字符集服务

基于范围的循环表达式

for ( decl : coll ) {

        statement

}

coll必须是支持迭代器的容器,或者是数组,或者是值列表类型

右值引用类型(C 11)

左值和右值都是针对表达式而言的,左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对象。

所谓右值引用就是引用一个右值对象(临时对象),比如下面的例子:

int&& ref = 1   2; // rvalue reference
ref  = 3;
cout << ref; // "6"

ref 对应的是 1 2的结果3,这是个临时对象。传统的C 引用方式是无法引用到这个临时对象的。右值引用主要是解决效率问题,具体的方法可以搜索 “C 移动语义”。

 

移动语义和右值引用

避免无意义的拷贝和暂存变量。

The programmer, however, has to specify that a move is possible unless a temporary is used.

std::move(),位于<utility> 。std::move(x)本身不会进行移动操作,只是将临时变量转换为一个右值引用(X &&x,使用双&声明,表明右值是可以修改的),表明此临时变量x将不会再使用了,可以将它的内容据为己有(不需要拷贝)。

移动之后不再使用原来的变量,原来的变量有效但是状态未定义。

void foo(X &x);//只接受左值

void foo(const X &x);//接受左值和右值

void foo(X &&x);//接受右值

原生字符串(raw string literals)

raw string 可以取消转义字符的作用,是 C 11 中添加的新特性。比如:

string escaped = "c:\Windows\System32\cmd.exe";

可以简写为:

string raw = R"(c:WindowsSystem32cmd.exe)";  

RAW String 开头要用大写的 R ,然后在双引号内要增加一对括号。

这个功能在其他的语言中早就有了。我们上边这个例子还不大能看出 raw string 的优势,但是如果常写正则表达式的话,就会感觉 raw string 太方便了。比如:

char str[] = R"(('(?:[^\']|\.)*'|"(?:[^\"]|\.)*")|)";

旧的写法是:

char oldstr[] = "('(?:[^\\']|\\.)*'|"(?:[^\\"]|\\.)*")|";

比特bit、字节byte、字word

原始字符串字面值、被编码的字符串字面值

Raw String Literals

此类型的字符串可包含特殊字符,语法R"delim(...)delim",delim是16个基本字符组成的分隔符除了反斜杠,空格,圆括号;

例如:R"(\n)"对应的普通字符串是"\n"

常用来定义正则表达式。

Encoded String Literals

使用编码前缀,定义特殊编码的字符串常量:

u8:utf-8,const char

u:char16_t

U:char32_t

L:wchar_t

新的 char 类型

C 11 中引入了 char16_t 和 char32_t 两种类型。这两种字符类型可以分别用来存储 utf-16 和 utf-32 编码的字符。相应的 string 类型也有两个变种, u16string 和u32string。

string s3 = u8"UTF-8 string";
u16string s4 = u"UTF-16 string";
u32string s5 = U"UTF-32 string";

字符串前的 u8、u和 U也是新增的特性,分别用来支持 UTF-8、UTF-16和UTF-32 字符串。

1byte=8bit

关键字noexcept

声明一个函数不能或不准备抛出异常。

void foo() noexcept;

若在foo函数内部没有处理发生的异常,程序会终止,调用std::terminate(),它默认调用std::abort();

for 循环

C 11 对 for 循环做了扩展,for 循环支持一种新的语法。

int a[3] = {1, 2, 3};
for (int &i : a) 
{
    cout <

word的大小与机器有关,一般为4byte

关键字constexpr

使得表达式在编译期间判断是否是常量,或者修饰返回值返回一个常量。

constexpr int square (int x){

               return x * x;

}

float a[square(9)]; // OK since C 11: a has 81 elements

auto 和 decltype 关键字

这两个关键字都是 C 11 中引入的。auto 关键字告诉编译器自动推导变量的类型。比如下面的代码:

auto i = 5; // int
auto d = 3.14; // double
auto b = false; // bool

如果我们希望推导出的类型是引用类型。那么需要在 auto 之后加个 &。比如下面这样:

int& iRef = i;
auto myAuto = iRef; // int
auto& myRef = iRef; // int&

用 auto 之后可以简化许多代码。比如下面这个代码:

vector myVector { 1, 2, 3 };
for(vector::size_type i = 0; i != myVector.size(); i  ) 
{
    cout << myVector[i]; 
}

用 auto 的话可以写为:

for(auto i = 0; i != myVector.size(); i  ) 
{
    cout << myVector[i]; 
}

当然,用上 for 的新语法,还可以写的更简便:

for (auto& x : myVector) 
{ 
    cout << x << endl; 
} 

decltype 与 auto 有些类似,它可以用来推导一个表达式的类型,比如下面的例子:

int a = 0b10'001'000;
cout << a << endl;
decltype(a) c = a   1; //int
cout << c << endl;

decltype(3) b = 3; // int&&

需要解释一下的是这个例子中 3 是个临时变量。所以推导出 b 的类型是一个 int 型的右值引用。但是作为函数返回值时,推导出的就不是右值引用了。

decltype(5) getFive() { return 5; } // int

C 11 中 auto 和 decltype 还可以配合使用,用来推导函数的返回值类型。下面是个例子:

auto getValue(int x) -> decltype(x) { return x; } // int

这么写还是挺繁琐的, C 14 中做了简化。可以简单的写为:

auto getValue(int x) { return x; } // int

不过我感觉这两种函数写法作用都不大,因为我们没法在头文件中把函数声明写为:

auto getValue(int x);

因为没有函数体,根本无法做类型推导…

C 14 中还支持如下的写法:

decltype(auto) = 3; // int&&
decltype(auto) getRef(int& x) { return x; } // int&

这些写法知道也就行了,用处不大。

 

模板特性

Variadic Templates

可变模板参数个数,例如处理不同类型的参数

void print (){}

template<typename T, typename... Types>

 void print (const T& firstArg, const Types&... args)

{

           std::cout << firstArg << std::endl; // print first argument

            print(args...); // call print() for remaining arguments

}

Alias Templates (Template Typedef)

template<typename T>

using Vec = std::vector>; // standard vector using own allocator

Vec coll;//即std::vector<int, MyAlloc<int>> coll;

Lambda 函数

Lambda 函数的概念最早应该来源于 Lisp 语言,现在也被 C 11 吸收进来了。 Lambda 函数使得我们可以像定义一个变量一样定义一个函数。比如下面这样:

auto sum = [](int x, int y) -> int {return x   y;};
cout << sum(2, 3);

上面的函数还可以简写为:

auto sum = [](int x, int y) { return x   y; };

编译器会自动推导返回值的类型。

到了 C 14 Lambda 函数更是支持了泛型。

auto sum = [](auto x, auto y) {return x   y;};  
cout << sum(2, 3) << endl;
cout << sum(2.2, 3.0) << endl;
cout << sum(2.2, 3) << endl;

Lambda 函数也可以作为函数的参数传递给函数。下面是个例子:

#include 
#include 
using namespace std;
void call(int arg, function func) 
{
    func(arg);
}
int main() 
{
    auto printSquare = [](int x) { cout << x*x; };
    call(2, printSquare); // "4"
}

上面的例子其实还说明 Lambda 函数不是普通的函数。它是一种特殊类型的对象。比如下面的 Lambda 函数:

auto sum = [](int x, int y) {return x   y;};  

写完整了应该是 :

function sum = [](int x, int y) {return x   y;};  

Lambda 函数还有一些高级用法。比如Lambda 函数中的 “[]” 是有作用的。用它可以将所在域的其他变量引入到函数中。比如下面的例子:

void call(function func) { func(); }
int main() 
{
    int i = 2;
    auto printSquare = [i]() { cout << i*i; };
    call(printSquare); // "4"
}

Lambda 函数中 [] 里按值传进去的参数是只读的。所以下面的代码是错的:

int a = 10;
int b = [a](int i) { a  ; return a * i; } (5); // 50

我们可以添加一个 mutable 关键字使得 a 不是只读,但是 a 值的改变是不会影响函数外面的。

int a = 10;
int b = [a](int i) mutable { a  ; return a * i; } (5);
cout << b << endl; // 55
cout << a << endl; // 10

Lambda 函数还可以是无名函数,这时定义函数的同时也要调用这个函数。否则因为这个函数没有名字,之后就没有调用的机会了。下面这两种写法结果是相同的。

cout << [](int i) { return i*i; } (101) << endl;

auto printSquare = [](int i) { return i*i; };
cout << printSquare(101) << endl;

利用 “[]” 也可以把结果传出来。下面这两种方法结果也是相同的。

int a = [](int i) { return i * i; } (11);
cout << a << endl;

[&a] (int i){ a = i * i;}(12);
cout << a << endl;

C 14 还支持一些新的特性,比如下面这样:

int a = 1;
[&, b = 2]() { a  = b; }();
cout << a; // "3"

关于 Lambda 函数,知道这些也就差不多了。

第一篇先写这么多。下一篇写写关于类和对象的一些新特性。

学习笔记(一些新特性总结 1) C 学习笔记(一些新特性总结 1) 虽然我也用了 C 有挺多年了,但是一直本着够用就行的原则,没有特...

signed和unsigned

lambda表达式

基本语法:

[ capture list ] { function body } 或

[ capture list ]   ( paramters list )   mutable   throwSpec   -> retType { function body }

mutable、  throwSpec、  -> retType 可选

调用:直接调用、生成lambda变量间接调用

[ ] { std::cout << "hello lambda" << std::endl; } (); 或

auto func = [ ] (const std::string &s){ std::cout << "hello lambda"  <<s << std::endl; };

func("good");

使用尾置返回:

未指明返回值类型时,若只有一个return语句,根据返回值自行推断;若有其他语句则返回void。

捕获规则:全局变量不用捕获即可使用

[ ]:不捕获任何变量

[=]:值捕获本作用域外变量

[&]:引用捕获作用域外变量

[x, &y]:显式值捕获x,引用捕获y

[=, &y]:值捕获除y的所有变量,y为引用捕获

[&, x]:引用捕获除x的所有变量,x为值捕获

值捕获变量在定义lambda时就已经确定,在内部不可更改其值,但使用mutable说明符可以使之改变。

lambda的类型

lambda的类型是匿名函数,每个不同的lambda的类型是不一样的。

#include<functional>

例如表达式

[ ] (int a, int b) -> int {  return a b; }

的类型是std::function<int(int ,int)>,用作返回值类型,可以返回一个lambda对象

std::function<int(int, int)>returnLambda () {

            return [] (int x, int y) { return x*y; };

}

auto f = returnLambda();

cout <<f(1,2)<<endl;

对于char类型来说,其实现在不同的机器上可能是不同的,有些是signed,有些则是unsigned,因此在需要用char进行数学算术运算的时候,应该指明符号。

关键字decltype

编译器推断表达式的类型:用于声明返回值类型,元编程或传递lambda的类型

std::map<std::string, sloat> coll;

decltype(coll)::value_type elem;

新的函数声明语法

template<typename T1, typename T2>

auto add(T1 x, T2 y) -> decltype(x y);//尾置返回,确定返回类型必须预先知道x,y的类型,但返回类型推断放在函数名前面无效(x,y类型此时未知)

将一个负数,强制转换为一个无符号的数字的时候,结果为这个负数加上无符号数的模。

作用域枚举(强枚举,枚举类)

enum class Salutation : char { mr, ms, co, none };

1,不可隐式的转换到int或从int转换

2,使用作用域运算符引用Salutation::mr;

3,可以显式定义类型(:char),否则默认是:int

4,可前向声明枚举类型

例如,将-1转换为unsigned short:unsigned short的模为65536,则unsigned short(-1)的结果为65535

新的基本数据类型

char16_t, char32_t, long long, unsigned long long ,std::nullptr_t

更深刻的理解是,将一个负数转换成无符号数字的时候,直接是将其补码的符号位1,当做正常的无符号数字解读,其内存中的数据没有变化,如下:

其他新特性

Nontype Template Parameters

bitset<32> flags32; // bitset with 32 bits

bitset<50> flags50; // bitset with 50 bits

Default Template Parameters

template<typename T, typename container = vector<T>>

class MyClass;

MyClass<int> x1;//即MyClass<int, vector<int>>

Keyword typename

用来说明其修饰的东西是类型

Member Templates

类的成员函数可以为模板

Nested Class Templates

嵌套类也可以为类模板

显式初始化基本数据类型

使用不带参数的显式构造初始化基本数据类型时,为0初始化(所有值都为0)

int i1; // undefined value

int i2 = int(); // initialized with zero

int i3{}; // initialized with zero (since C 11)

    cout<<short(0xffff)<<endl;                    //输出-1
    cout<<unsigned short(0xffff)<<endl;            //输出65535
    cout<<unsigned short(short(0xffff))<<endl;    //输出65535

main函数的定义

1,

int main{}

2,

int main (int argc, char* argv[]){}

不一定要return 语句,隐式返回0,表示成功执行;返回非0则表示出错;

不使用return来结束程序可使用exit(), quick_exit(), terminate();

 

进制表示

15 十进制,015 八进制,0x15十六进制

 

字符串可以分行书写

    cout<<"姓名 学号n"
          "王五 0125";

转义序列

后紧跟1-3个八进制数字

x后紧跟1-*个十六进制数字

字面值前后缀

前缀

u Unicode 16字符 char16_t

U Unicode 32字符 char32_t

L 宽字符   wchar_t

u8 UTF-8   char[]字符串

后缀

u/U unsigned

l/L   long

ll/LL long long

f/F   float

l/L   long double

类型可以组合,比如42ULL为unsigned long long

2.2 变量

变量初始化

int value1 = 0;
int value2 = {0};
int value3(0);
int value4{0};
//以上四个效果相同

vector<int> value5{1, 2, 3, 4, 5};//存储了1 2 3 4 5
vector<int> value6(10,-1);//存储了10个-1

内置类型(int、double、char)在定义时如果没有给定初始值,将不被初始化。

访问全局变量

int value=10;
int main()
{
    int value=5;//覆盖了全局变量value
    int newValue=::value;//使用::访问全局变量
}

2.3 复合类型

引用reference

int &rValue=value; 变量或者对象的别称,占用同一块内存,在声明引用的时候必须初始化,初始化后不可改变引用的变量或对象。

指针pointer

int *pValue=&value; 声明一个变量,其存储的是另外一个变量的地址。

空指针:

int *pValue=nullptr;

int *pValue=0;

int *pValue=NULL; //需要include<cstdlib>

void *指针

任何类型都可以用void*指针,可以认为void*指针就是对应一块内存区域。

2.4 const限定符

指针和const

const int value = 32;    //value对应的内存不能改变

//指向常量的指针pointer to const
const int *cpValue = &temp;    //cpValue对应的内存可以改变(可以重新指向另一个变量),但是temp不可以通过cpValue改变(指向的变量不能更改)

//常量指针const point
int *const pcValue = &temp;      //pcValue对应的内存不能更改(不可以重新指向另一个变量),temp可以通过pcValue更改(指向的变量可以更改)

//指向常量的常量指针
const int *const cpcValue = &temp;//都不可以更改

补充:const int *const p = &value,其中第二个const是顶层,限制p的内存不能更改;第一个const是底层,限制指向的内存不能改。

constexpr和常量表达式

常量表达式指的是在编译的时候就可以确定的值的常量。

比如下边两个都是常量表达式:

const int max_files = 20;
const int limit = max_files   1;

但是有时候不能确定一个语句是不是常量表达式,这就可以constexpr进行变量声明,由编译器验证是不是常量表达式:

constexpr int limit = mf   1;//只有当mf是编译时确定值,表达式才能通过编译

2.5 类型的处理方式

类型别名

typedef double wages, *pWages;//wages是double的别名,pWages是double*的别名

using db = double;//C 11中支持的

auto

auto item = v1 v2;//由编译器推断item的类型

decltype

选择并返回操作数的数据类型

decltype( f() ) sum = x;

当操作数加括号,表示操作数的引用类型

decltype( (f()) ) sum = x;

 

 

本文由9159.com发布于编程,转载请注明出处:9159.com:int相同(除了布尔型和扩展字类型(例如

关键词: 9159.com