C++数据类型 decltype

转载自http://www.cppblog.com/flyinghare/archive/2011/06/23/149225.html

C++0x引入了新的关键字decltype,它是一个操作符,用来取得表达式的类型,主要在泛型编程中使用。这里,简单介绍一下语法规则。

语法形式:decltype (expression)
其中,这里的括号必不可少(这点不同于sizeof操作符)。decltype(e)可看到是一个类型别名,并且不会对表达式e进行计算(即只有编译时行为而无运行时行为)。另外,不允许把decltype作用于一个类型,因为没有任何理由要这样做。

确定decltype(e)类型的规则如下:
Rule-1. 如果e是一个标识符表达式或者类成员访问表达式,那么decltype(e)就是e所命名的实体的类型。如果没有此实体或者e命名了一个重载函数集,那么程序是ill-formed的。
Rule-2. 如果e是一个函数调用或者一个重载操作符调用(忽略e外面的括号),那么decltype(e)就是该函数的返回类型。
Rule-3. 否则,假设e的类型是T:如果e是一个左值,则decltype(e)就是T&;否则(e是一个右值),decltype(e)就是T。

举例分析如下(内容来自参考Ref1):

eg1 名字空间或局部作用域内的变量(Rule-1)
int a;
int& b = a;
const int& c = a;
const int d = 5;
const A e;

(注:不能直接编译,这里写出来只是分析)
decltype(a) // int 
decltype(b) // int&
decltype(c) // const int&
decltype(d) // const int
decltype(e) // const A

但需要注意括号可能会影响结果,例如:
decltype((a));  // int& (此时(a)表达式不满足Rule-1和Rule-2,应用Rule-3,而表达式(a)是一个左值,所以为int&)

eg2 函数形参(Rule-1)
void foo(int a, int& b, float&& c, int* d)
{
    decltype(a) // int
    decltype(b) // int&
    decltype(c) // float&&
    decltype(d) // int*
}

eg3 函数类型(Rule-1)
int foo(char);
int bar(char);
int bar(int);

decltype(foo) // int(char)
decltype(bar) // error, bar is overloaded

但需要注意当形成函数指针时适用Rule-3:
decltype(&foo) // int(*)(char)
decltype(*&foo) // int(&)(char)

eg4 数据类型(Rule-1)
int a[10];
decltype(a)  // int[10]

eg5 成员变量(Rule-1)
class A {
    int a;
    int& b;
    static int c;
    
    void foo() {
        decltype(a)          // int
        decltype(this->a)    // int
        decltype((*this).a)  // int
        decltype(b)          // int&
        decltype(c)          // int (static members are treated as variables in namespace scope)
    }
    void bar() const {
        decltype(a)   // int
        decltype(b)   // int&
        decltype(c)   // int
    }
};

A aa;
const A& caa = aa;
decltype(aa.a)  // int
decltype(aa.b)   // int&
decltype(caa.a)  // int

但内置操作符.*和->*适用Rule-3:
decltype(aa.*&A::a) // int&
decltype(aa.*&A::b) // illegal, cannot take the address of a reference member
decltype(caa.*&A::a) // const int&

eg6 this(Rule-3)
class X {
    void foo() {
        decltype(this)    // X*,因为this是右值
        decltype(*this)   // X&,因为*this是左值
    }
    void bar() const {
        decltype(this)   // const X*
        decltype(*this)  // const X&
    }
};

eg7 指向成员变量和成员函数的指针(Rule-1)
class A {
    int x;
    int& y;
    int foo(char);
    int& bar() const;
};

decltype(&A::x)    // int A::*
decltype(&A::y)    // error: pointers to reference members are disallowed (8.3.3 (3))
decltype(&A::foo) // int (A::*) (char)
decltype(&A::bar) // int& (A::*) () const

eg8 字面值(Rule-3)
(字符串字面值是左值,其它字面值都是右值)
decltype("decltype") // const char(&)[9]
decltype(1) // int

eg9 冗余的引用符(&)和CV修饰符
由于decltype表达式是一个类型别名,因此冗余的引用符(&)和CV修饰符被忽略:
int& i = ...;
const int j = ...;
decltype(i)&         // int&. The redundant & is ok
const decltype(j)   // const int. The redundant const is ok

eg10 函数调用(Rule-2)
int foo();
decltype(foo())    // int
float& bar(int);
decltype (bar(1))  // float&
class A { ... };
const A bar();
decltype (bar())    // const A
const A& bar2();
decltype (bar2())  // const A&

eg11 内置操作符(Rule-3)
decltype(1+2)     // int (+ returns an rvalue)
int* p;
decltype(*p)        // int& (* returns an lvalue)
int a[10];
decltype(a[3]);     // int& ([] returns an lvalue)
int i; int& j = i;
decltype (i = 5)   // int&, because assignment to int returns an lvalue
decltype (j = 5)   // int&, because assignment to int returns an lvalue
decltype (++i);    // int&
decltype (i++);    // int (rvalue)

如何用程序验证decltype的结果?可以参考下面的程序对上面的分析结果进行验证:
F:\tmp>type decltype_eg1.cpp
#include <iostream>
#include <string>
using namespace std;

template <typename T>
string Foo()
{
    return "unknown";
}

template <>
string Foo<int>()
{
    return "int";
}

template <>
string Foo<const int>()
{
    return "const int";
}

template <>
string Foo<int &>()
{
    return "int&";
}

template <>
string Foo<const int&>()
{
    return "const int&";
}

class A{};

template <>
string Foo<A>()
{
    return "A";
}

int main()
{
    int a;
    int &b = a;
    const int &c = a;
    const int d = 5;
    A e;
    double f;

    cout << "a: " << Foo<decltype(a)>() << endl;
    cout << "b: " << Foo<decltype(b)>() << endl;
    cout << "c: " << Foo<decltype(c)>() << endl;
    cout << "d: " << Foo<decltype(d)>() << endl;
    cout << "e: " << Foo<decltype(e)>() << endl;
    cout << "f: " << Foo<decltype(f)>() << endl;
}


F:\tmp>g++ decltype_eg1.cpp -std=c++0x

F:\tmp>a.exe
a: int
b: int&
c: const int&
d: const int
e: A
f: unknown

F:\tmp>gcc --version
gcc (GCC) 4.3.0 20080305 (alpha-testing) mingw-20080502
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


参考资料:
Ref1: Decltype (revision 6): proposed wording
Ref2: Decltype (revision 7): proposed wording

转载于:https://www.cnblogs.com/weida/p/3621861.html

<think>好的,用户需要关于C++数据类型的详案。首先,我需要回忆C++中的基本数据类型,包括内置类型和复合类型。内置类型通常分为整型、浮点型、字符型、布尔型等。然后,复合类型可能包括数组、指针、引用、结构体、类、联合体、枚举等。 首先,内置数据类型部分,需要详细说明每种类型的大小、范围和用途。比如,整型有short、int、long、long long,不同平台下的大小可能不同,比如在32位系统中int通常是4字节,而64位可能也是4字节,但long可能是4或8字节。需要提到标准中的最小要求,比如short至少2字节,int至少和short一样大,long至少和int一样大,long long至少8字节。 浮点型包括float、double、long double,精度和范围不同。float通常是4字节(单精度),double是8字节(双精度),long double可能是8、10或12字节,取决于编译器和平台。 字符型有char、wchar_t、char16_t、char32_t,分别对应不同的字符集,比如char用于ASCII或UTF-8,wchar_t用于宽字符(如Unicode在Windows是2字节,Linux是4字节),char16_t和char32_t是C++11引入的,对应UTF-16和UTF-32。 布尔型bool,只有true和false,通常占1字节,但具体实现可能不同。 然后是复合数据类型。数组是同类型元素的连续存储,声明方式如int arr[5]。指针存储内存地址,如int* p。引用是变量的别名,必须初始化,如int& ref = var。结构体struct允许组合不同类型的数据,如struct Student { string name; int age; }。类class类似结构体,但可以包含成员函数和访问控制。联合体union允许不同数据类型共享内存,同一时间只有一个成员有效。枚举enum用于定义命名整型常量,如enum Color { RED, GREEN, BLUE }; 还有派生类型,如常量(const)、易变(volatile)、共用体(mutable)等类型修饰符。此外,C++11引入了类型别名(using)和类型推断(auto、decltype),这些也需要提及。 需要注意不同数据类型的存储大小和范围,可能因编译器和平台而异,建议使用sizeof运算符获取实际大小。另外,无符号整型(unsigned)和有符号整型(signed)的区别,无符号类型不能表示负数,但范围更大。 可能还需要提到void类型,表示无类型,用于函数返回值或指针。 总结时,需要结构清晰,分点说明内置类型和复合类型,每种类型的特点、示例和注意事项。这样用户能全面了解C++数据类型体系。 </think>C++数据类型体系可分为**内置(基本)数据类型**和**复合(派生)数据类型**两大类,以下是详细说明: --- ### 一、内置(基本)数据类型C++语言直接定义的基础类型,用于表示最基本的数据形式。 #### 1. 整型(整数或枚举值) - **有符号整型**:`signed char`、`short int`(或`short`)、`int`、`long int`(或`long`)、`long long int`(或`long long`,C++11引入)。 - 范围:`signed char`通常为-128~127(1字节);`short`至少2字节(如-32768~32767);`int`至少与`short`等大(常见4字节);`long`至少与`int`等大(32位系统4字节,64位系统8字节);`long long`至少8字节(-9,223,372,036,854,775,808~9,223,372,036,854,775,807)。 - **无符号整型**:`unsigned char`、`unsigned short`、`unsigned int`、`unsigned long`、`unsigned long long`。 - 范围:无符号类型仅表示非负数,如`unsigned char`为0~255(1字节),`unsigned int`(4字节)为0~4,294,967,295。 - **注意**:`char`默认是否有符号由编译器决定(可显式声明`signed char`或`unsigned char`)。 #### 2. 浮点型(实数) - `float`:单精度浮点,通常4字节(约6~7位有效数字)。 - `double`:双精度浮点,通常8字节(约15~17位有效数字)。 - `long double`:扩展精度浮点,大小由编译器决定(常见8/10/12字节)。 #### 3. 字符型 - `char`:存储单个字符(如ASCII或UTF-8编码),1字节。 - `wchar_t`:宽字符类型(如Unicode的UTF-16或UTF-32),大小由编译器决定(Windows为2字节,Linux为4字节)。 - `char16_t`(C++11):存储UTF-16编码字符,2字节。 - `char32_t`(C++11):存储UTF-32编码字符,4字节。 #### 4. 布尔型 - `bool`:表示逻辑值`true`(真)或`false`(假),通常1字节(实际存储时可能优化为位存储)。 #### 5. 空类型 - `void`:表示“无类型”,用于函数无返回值(如`void func()`)、无类型指针(`void*`)或占位符。 --- ### 二、复合(派生)数据类型 通过组合或修饰内置类型得到的类型,用于表示更复杂的数据结构。 #### 1. 数组(Array) - 同类型元素的连续内存块,声明形式:`类型 数组名[大小]`(如`int arr[5];`)。 - 大小需为编译期常量(C++11起支持`constexpr`或动态数组(如`std::vector`更常用))。 #### 2. 指针(Pointer) - 存储变量内存地址的类型,声明形式:`类型* 指针名`(如`int* p = &num;`)。 - 特殊指针:空指针(`nullptr`,C++11)、野指针(未初始化的危险指针)、void指针(可指向任意类型,但需强制转换后使用)。 #### 3. 引用(Reference) - 变量的别名,声明后必须初始化且不可重新绑定,声明形式:`类型& 引用名 = 变量`(如`int& ref = num;`)。 - 用途:函数参数传递(避免拷贝)、操作符重载(如`operator=`)。 #### 4. 结构体(Struct) - 自定义复合类型,可包含不同类型的成员变量,声明形式: ```cpp struct Student { std::string name; // 成员变量 int age; }; ``` #### 5. 类(Class) - 面向对象的核心类型,可包含成员变量、成员函数及访问控制(`public`/`private`/`protected`),声明形式: ```cpp class Circle { private: double radius; public: double area() { return 3.14 * radius * radius; } }; ``` #### 6. 联合体(Union) - 所有成员共享同一块内存的类型,同一时间仅一个成员有效,声明形式: ```cpp union Data { int i; float f; char str[20]; }; // 占用内存为最大成员的大小(此处20字节) ``` #### 7. 枚举(Enum) - 定义命名整型常量的类型,声明形式: ```cpp enum Color { RED, GREEN, BLUE }; // RED=0, GREEN=1, BLUE=2(默认从0开始) // C++11起支持强类型枚举(enum class): enum class Status : int { OK=200, ERROR=500 }; // 限定作用域,需显式转换为整型 ``` --- ### 三、类型修饰符 - `const`:修饰变量为只读(如`const int MAX = 100;`)。 - `volatile`:告知编译器变量可能被外部修改(如硬件寄存器),禁止优化读取。 - `mutable`:允许`const`对象的成员变量被修改(仅用于类成员)。 --- ### 四、类型推断(C++11起) - `auto`:根据初始化值自动推导类型(如`auto x = 3.14;` → `double`)。 - `decltype`:推导表达式的类型(如`decltype(x) y = 5;` → `double y`)。 --- ### 总结 C++数据类型体系灵活且强大,内置类型提供基础数据表示,复合类型支持复杂数据结构,类型修饰符和C++11后的特性(如`auto`、`enum class`)进一步提升了类型安全性和开发效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值