C++类型系统(现代C++)

类型的 概念是非常重要的是 C++。 每个变量、函数参数和函数返回值必须具有类型来编译。 此外,(包括文本值) 编译器隐式地为每个表达式一个类型,则在计算之前。 类型的一些示例包括 int 存储整数值,double 存储浮点值 (也称为标量数据类型),或者标准库选件类 std::basic_string 存储文本。 您可以通过定义 class 或 struct创建自己的类型。 该类型指定为变量的内存量 (或表达式结果) 将被赋值,该变量的一个值,这些值 (作为位组合) 如何解释和操作可以存储可在该。 本文包含 C++ 类型系统的主要功能非正式的概述。

术语

变量:一个数据量的符号名,以便该名称可以用于访问数据它是指在定义代码的范围中。 在 C++ 中,“变量”通常用于引用标量数据类型的实例,而其他类型的实例通常称为“对象”。

对象:为简单起见和一致性,本文使用术语“对象”是指选件类或结构的所有实例,并在常见来说时使用它包括所有类型,即使标量变量。

POD 类型 (纯旧数据):此非正式的类别数据类型 C++ 引用标量的类型 (请参见基础类型部分) 或是 POD 选件类。 POD 选件类没有也不是 POD 的静态数据成员,并没有用户定义的构造函数、用户定义的析构函数或用户定义的赋值运算符。 此外,POD 选件类没有虚函数、基类和不私有或受保护的非静态数据成员。 POD 类型为外部数据交换非常常用的,例如通过在只有 POD 类型) 的 C 语言编写的模块 (。

指定变量和函数类型

C++ 是 强类型的 语言,并且还 静态类型化;每个对象都有一个类型,该类型从不更改 (与静态数据对象不混淆)。
在代码中,您的在声明变量 必须或显式指定其类型,或者使用 auto 关键字指示编译器从该初始值设定项推导该类型。
在代码中,您的在声明函数 必须指定每个参数的类型,该方法的返回值或 void,如果值不受该函数返回。 异常是使用函数模板,允许任意类型的参数。

在您先声明变量后,无法更改其类型在以后的几点。 但是,您可以复制变量值或函数的返回值赋给其他类型的另一个变量。 此类操作调用 类型转换,有时需要的,但也是数据丢失或不正确的潜在的源。

在声明 POD 类型的变量时,强烈建议您将其初始化,这意味着为其指定初始值。 直到初始化变量,它具有包含的一个“垃圾”值任何位之前会在该内存位置。 特别是在将来自另一种语言您的,处理初始化这是需要注意的 C++ 的一个重要方面。 在声明非 POD 选件类类型的变量,构造函数处理初始化时。

下面的示例演示了一些说明的一些简单变量声明的每一。 该示例还演示编译器如何使用类型信息允许或禁止在变量中某些后面的操作。

    int result = 0;              // Declare and initialize an integer.
    double coefficient = 10.8;   // Declare and initialize a floating 
                                 // point value.
    auto name = "Lady G.";       // Declare a variable and let compiler 
                                 // deduce the type.
    auto address;                // error. Compiler cannot deduce a type 
                                 // without an intializing value.
    age = 12;                    // error. Variable declaration must
                                 // specify a type or use auto!
    result = "Kenny G.";         // error. Can’t assign text to an int.
    string result = "zero";      // error. Can’t redefine a variable with
                                 // new type.
    int maxValue;                // Not recommended! maxValue contains 
                                 // garbage bits until it is initialized.

基本 (固定) 类型

与有些语言不同,C++ 没有其他类型派生的泛型基类型。 该语言的 Visual C++ 实现包括许多 基本类型,也称为 内置类型。 这包括数字类型 (如 int,double,long,bool,以及 ASCII 和 UNICODE 字符的 char 和 wchar_t 类型,它们。 大多数基础类型 (除外 bool、double、wchar_t 和相关类型) 都具有未签名的版本,修改的值范围变量可以存储。 例如,int,存储 32 位带符号整数,可以表示从 -2,147,483,648 的值为 2,147,483,647。 unsigned int,还存储为 32 位,可存储从 0 的值为 4,294,967,295。 可能的值的总数在每种情况的相同;仅数组大小是不同的。

基础类型由编译器识别,具有固定规则管理操作可以针对它们执行,因此,它们可以转换为其他基础类型。 有关完整的内置类型,并且它们的大小和数目限制,请参见 基础类型(C++)

下图显示了内置类型的相对大小:

内置类型大小(以字节为单位)

下表列出了常用的基础类型:

类型

大小

Comment

int

4 个字节

整数值的默认值选择。

double

8 个字节

浮点值的默认值选择。

bool

1 个字节

表示可以为 true 还是 false 值。

char

1 个字节

ASCII 字符用于无需转换为 UNICODE 的早期 C 样式字符串或 std::string 的对象。

wchar_t

2 个字节

表示“无法解码为 UNICODE 格式的宽”字符值 (在 windows 的 UTF-16,其他操作系统可能不同)。 这是用于类型 std::wstring字符串的字符类型。

unsigned char

1 个字节

C++ 不具备内置 byte 类型。 使用 unsigned char 表示字节值。

unsigned int

4 个字节

默认位标志的选择。

long long

8 个字节

表示非常大整数值。

无效类型

void 类型是一种特殊类型的;不能声明类型 void的变量,但是,您可以声明类型 void * (可 void的指针) 变量,有时是必要的,因为分配基元 (非类型化) 时内存。 但是,对于 void 的指针不是类型安全的,因此使用它们将在现代 C++ 强通常是不鼓励。 在函数声明,void 返回值表示该函数不返回值;这是对 void的常见和接受使用。 在 C 语言要求后已被声明为零的参数中的 void 的功能在现代 C++ 参,例如,fou(void),此做法将不鼓励,应声明 fou()。 有关更多信息,请参见类型转换和类型安全(现代C++)

const 类型限定符

任何内置或用户定义的类型可以由关键字限定常数。 此外,成员函数可以是 const-限定甚至 const-重载。 const 类型的值,在初始化后,无法修改。

    const double PI = 3.1415;
    PI = .75 //Error. Cannot modify const variable.

const 限定符在功能广泛使用,并且变量声明和“const 有效性”是 C++ 中的一个重要概念;它实质上表示使用 const,确保在编译时,不会无意修改值。 有关更多信息,请参见const (C++)

const 类型从其非常量版本截然不同;例如,const int 是从 int的不同类型。 当您必须从变量时,将移除 const 状态 可以使用这些极少情况下的 C++ const_cast 运算符。 有关更多信息,请参见类型转换和类型安全(现代C++)

字符串类型

严格来说,C++ 语言没有内置的“字符串”类型;char 和 wchar_t 存储单个字符–必须声明为这些类型关闭字符串,添加一个终止 null 值 (例如,ASCII ‘\0’) 到通过最后一个有效字符数组元素为 (也称为“C 样式字符串")。 C 样式字符串需要更多代码编写或使用外部字符串实用工具函数。 但是,在现代 C++,建议具有标准库类型 std::string (对于 8 位 char类型的字符串。std::wstring ) 或 (对于 16 位 wchar_t类型的字符串))。 这些 STL 容器中赋值,在本机字符串类型,因为它们是在所有兼容 C++ 生成环境包括标准库的一部分。 请使用 #include <string> 指令使这些类型可用在您的程序。 (如果使用的是 MFC 或 ATL,CString 选件类也可用,但是,不是 C++ 标准的节。)使用 null 终止的字符数组 (前面提到的 C 样式字符串) 在现代 C++ 强烈建议。 有关如何确定哪个的更多信息字符串类型的一个现代 C++ 程序以及如何将各种类型之间,请参见 字符串和文本(现代C++)

用户定义的类型

在定义 class、struct、union或 enum,构造用于其余部分您的代码,好像它是一个基础类型。 它具有已知的范围在内存中,因此,有关如何的某些规则可以使用该应用于它编译时检查的,因此,运行时,在程序的生存期。 基本内置类型和用户定义的类型之间的主要区别如下:

  • 编译器没有用户定义的类型的内置知识。 当在编译时首先遇到该定义过程时,它将“了解”该类型。

  • 您指定操作中的类型上执行,因此,它如何能转换为其他类型,定义 (通过重载) 适当的运算符,作为选件类成员或非成员函数。 有关更多信息,请参见重载

  • 它们不必静态类型化 (目标类型从不更改) 的规则。 通过 继承 和 多态性结构,作为选件类的一个用户定义的类型声明的变量 (称为选件类的对象实例) 可能具有不同的类型运行时比在编译时。 有关更多信息,请参见派生类

指针类型

通过使用特殊声明 * (星号),追溯到 C 语言的早期版本中,C++ 继续可以将指针声明类型的变量。 指针类型在存储实际数据值的内存存储位置的地址。 在现代 C++,这些在代码中引用 的原始指针和访问通过特殊运算符 * (星号) 或 -> (短划线与大于)。 这称为 间接引用,然后哪个使用的取决于您是否取消引用指针。标量或指向对象的成员。 使用指针类型一起使用长为某个程序开发的 C 和 C++ 的最具挑战性和最 scrum 的方面。 本节概述这些情况和做法有助于使用原始的指针,如果愿意,但是,在现代 C++ 不再需要 (或建议) 为对象的所有权使用原始的指针,因为 智能指针 的发展 (讨论更多本部分的末尾)。 为观察对象使用原始的指针有用且安全的,因此,但是,如果必须为对象的所有权使用它们,则应这样做非常小心和仔细的考虑它们所属对象如何创建和销毁。

您应该知道的第一点声明变量将仅发布内存需要存储内存位置地址指针引用的原始的指针,以便在取消引用时。 (也称为 后备存储) 未分配内存的分配数据的值。 换言之,通过声明一个基元的指针变量,则会创建一个内存地址变量,而不是实际数据变量。 取消引用以确保之前的指针变量它包含有效地址到备份存储在您的程序将导致未定义的行为 (通常是致命错误)。 下面的示例演示这种错误:

    int* pNumber;       // Declare a pointer-to-int variable.
    *pNumber = 10;      // error. Although this may compile, it is
                        // a serious error. We are dereferencing an
                        // uninitialized pointer variable with no
                        // allocated memory to point to.

该示例取消引用指针类型没有任何内存分配存储实际整数数据或有效的内存地址分配给它。 下面的代码纠正这些错误:

    int number = 10;          // Declare and initialize a local integer
                              // variable for data backing store.
    int* pNumber = &number;   // Declare and initialize a local integer
                              // pointer variable to a valid memory
                              // address to that backing store.
...
    *pNumber = 41;            // Dereference and store a new value in 
                              // the memory pointed to by
                              // pNumber, the integer variable called
                              // “number”. Note “number” was changed, not
                              // “pNumber”.

已纠正代码示例使用本地堆栈内存创建 pNumber 指向的备份存储区。 我们为使用基本类型。 实际上,指针的备份存储区是通常在内存区域动态分配调用 堆 的用户定义的类型 (或“自由存储") 使用 new 关键字表达式 (在 C 编程,较旧的 malloc() C 运行库函数使用了)。 在分配,这些“变量”通常称为“对象”,特别是,如果它们类定义。 随 new 的内存必须由一个对应的 delete 语句 (删除;或者,如果使用 malloc() 函数分配时,C 运行时函数 free())。

但是,忘记删除动态分配的对象特别是在复杂代码非常容易,导致调用 内存泄漏的资源 bug。 为此,请使用原始的指针在现代 C++ 强烈建议。 包装在 智能指针的基元的指针几乎总是最好的,将自动释放内存,其析构函数调用时 (当代码超出智能指针的大小时);使用智能指针您实际需要消除缺陷整个选件类在 C++ 程序的。 在下面的示例中,假定 MyClass 是具有公共方法 DoSomeWork();的用户定义的类型

void someFunction() {
    unique_ptr<MyClass> pMc(new MyClass);
    pMc->DoSomeWork();
}
  // No memory leak. Out-of-scope automatically calls the destructor
  // for the unique_ptr, freeing the resource.

有关智能指针的更多信息,请参见 智能指针(现代C++)

有关指针转换的更多信息,请参见 类型转换和类型安全(现代C++)"。

有关指针的更多信息,请参见 指针

windows 数据类型

在编程用于 C 和 C++ 的经典 Win32,大多数功能使用窗口特定函数和 #define 宏 (定义在 windef.h) 指定参数和返回值的类型。 这些“窗口数据类型”是主指定特殊名称 (别名) 将 C/C++ 内置类型。 有关完整的这些函数,并且预处理器定义,请参见 Windows Data Types。 某些函数,例如 HRESULT 和 LCID,有用且声明性的。 其他,例如 INT,没有特殊含义并一直是 C++ 类型的别名。 其他窗口数据类型与日 C 编程和 16 位处理器保留的名称,并且没有用途或意味着在现代硬件或操作系统。 还有特定的数据类型与窗口运行库,列表作为 Windows Runtime base data types。 在现代 C++,原则是首选 C++ 基础类型,除非 windows 类型将有关该值如何的一些附加含义将被解释。

更多信息

有关 C++ 类型系统的更多信息,请参见下列主题。

值类型(现代C++)

描述 值类型 以及问题与其使用相关。

类型转换和类型安全(现代C++)

描述常见类型转换问题以及如何避免它们。

请参见

其他资源

返回C++ (现代C++)的欢迎

C++语言参考

标准C++库参考