# 零、前言

## 商标等。

作为一名退休律师，我觉得有必要加入这个简短的部分，除非你是这些公司或组织的律师，否则你可能不会在意。这篇序言的其余部分对非律师来说是更令人愉快的阅读，所以请不要让它影响你。微软、Visual Studio、Visual C++、Visual C#、Windows、Windows NT、Win32、MSDN、Silverlight、DirectX 和 IntelliSense 是微软公司的注册商标。GNU 是自由软件基金会的注册商标。国际标准化组织是国际标准化组织的注册服务标志。国际电工委员会是国际工程联合会的注册服务标志。统一码是统一码联合会的注册服务标志。英特尔是英特尔公司的注册商标。其他商标和服务标志是其各自所有者的财产。

## 程序入口点

在 C# 中，程序的入口点是一个名为`Main`的静态方法。由于各种框架都提供了自己的框架(例如 Silverlight)，所以您通常不会真正看到它，但是它就在那里的某个地方，因为如果没有它，操作系统将不知道从哪里开始执行您的程序。

C++ 程序的入口点是`main`函数。一个简单的版本如下所示:

```cpp
    int main(int argc, char* argv[])
    {
          // Your program starts here.

          // Returning 0 signifies success.
          return 0;
    }

```

参数是参数计数，后跟一个命令行参数数组(作为字符串)。在 Windows 编程中，您通常会将此视为切入点:

```cpp
    int wmain(int argc, wchar_t* argv[])
    {
          // Your program starts here.

          // Returning 0 signifies success.
          return 0;
    }

```

这个`wmain`入口点是微软特有的。它被用作 Windows Unicode 程序的[入口点(相对于旧的 ASCII/代码页程序)。支持 Unicode 的微软操作系统(从 Windows 2000 和 Windows NT 4 上的所有内容，甚至在安装特殊附加组件时基于 Win 9X 的系统)使用 UTF-16 编码。因此，你真的应该在编写程序时一直使用统一码，除非你绝对需要支持不支持统一码的旧系统。](http://msdn.microsoft.com/en-us/library/6wd819wh(VS.110).aspx)

您还会经常看到这是 Windows 程序的入口点:

```cpp
    #include <tchar.h>

    int _tmain(int argc, _TCHAR* argv[])
    {
          // Your program starts here.

          // Returning 0 signifies success.
          return 0;
    }

```

Windows SDK 提供了 **tchar.h** 头文件，当您需要构建将在 Unicode 和非 Unicode 版本的 Windows 上使用的项目时，您可以(并且应该)使用该头文件。我不在样品中使用它，因为我想尽可能使样品便携并符合标准。

相反，我编写了一个小头文件 **pchar.h** ，它简化了入口点可移植性问题。这不能解决处理字符串时出现的大多数可移植性问题；不幸的是，字符串可移植性是 C++ 中不容易的一个领域。事实上，我这里的头文件是*而不是*，这是一个很好的例子，说明当您实际上需要命令行参数时该怎么做。我们将在本书后面更详细地讨论字符串。现在，首先，这里是头文件:

样本:pchar.h

```cpp
    #pragma once

    #if !defined(_PCHAR_H)
    #define _PCHAR_H 1

    #if defined(WIN32) && defined(UNICODE)
    #define _pmain wmain
    #define _pchar wchar_t
    #else
    #define _pmain main
    #define _pchar char
    #endif

    #endif

```

其次，这里是入口点现在的样子(我在这里省略了头文件的包含):

```cpp
    int _pmain(int /*argc*/, _pchar* /*argv*/[])
    {
          // Your program starts here.

          // Returning 0 signifies success.
          return 0;
    }

```

可以看到，参数名被注释掉了(使用 C 风格的注释，即`/*...*/`)。这在 C++ 中是完全合法的，并且每当您有一个需要具有某些参数的函数时，您都应该这样做，尽管您可能不打算使用这些参数。通过注释掉参数名称，您可以确保不会意外使用它们。

**pchar.h** 中的代码给了我们一个合理的可移植入口点，而`int _pmain(int, _pchar*[])`入口点本身确保了我们永远不会使用传入的命令行参数。如果您需要命令行参数，那么这个解决方案将不起作用——您需要一个更高级、更复杂的解决方案。

## 参数和参数

我在本书的不同地方使用了术语*参数*和*参数*。对我来说，参数是在程序中调用时传递给函数的值，而参数是函数规范的一部分，它告诉程序员函数预期接收某一类型的值。它还告诉程序员如何处理这个值。一个参数通常会提供一个可以引用该值的名称，尽管 C++ 允许我们只提供一个类型，如果我们需要一个特定的参数(例如，匹配一个接口规范)，但并不打算实际使用它的值。

作为一个参数对一个参数的例子，在 C# 中你可能有一个类方法，比如`void AddTwoNumbers(int a, int b, ref int result) { result = a + b; }`。这种情况下，`a`、`b`、`result`为参数；我们知道`AddTwoNumbers`可能会改变为`result`参数传递的参数的值(事实上确实如此)。如果你这样调用这个方法，`int one = 1, two = 2, answer = 0; someClass.AddTwoNumbers(one, two, ref answer);`那么`one`、`two`和`answer`都是传递给`AddTwoNumbers`的参数。

## 语法高亮显示

本书中的代码示例使用了 Visual Studio 2012 Ultimate RC 中的语法高亮颜色。这将帮助你理解代码，但你也可以在单色电子书阅读器上阅读。

## 样品

这本书的样品可以在[https://bitbucket.org/syncfusion/cpp_succinctly](https://bitbucket.org/syncfusion/cpp_succinctly)买到。

本书的示例是使用 Visual Studio 2012 Ultimate RC 设计和开发的。VS 2012 附带的 C++ 编译器包含了 Visual Studio 2010 中没有包含的 C++ 11 语言标准的新功能。2012 年秋季，[微软将发布免费的 Visual Studio 2012](http://blogs.msdn.com/b/visualstudio/archive/2012/06/08/visual-studio-express-2012-for-windows-desktop.aspx) 的“Express”版本，该版本将允许开发人员使用 C++ 目标桌面应用程序(如示例使用的控制台应用程序)。在此之前，为了充分利用这些示例，您将需要一个非 Visual Studio 2012 Express 版本。

我一路上用[极简 GNU for Windows (MinGW)](http://mingw.org/) 测试了很多样例，所以应该有很多跨编译器的可移植性。我可以肯定的是，MinGW 提供的 GCC 编译器编写的一个示例不工作，那就是**存储比率示例**。它利用微软专用语言扩展`_declspec(thread)`来模拟`thread_local`存储。GCC 有自己非常相似的扩展，其他编译器供应商无疑也有，所以如果你用适合你决定使用的编译器的代码替换它，那么它应该编译并运行。

最后，这些示例都是控制台示例。我选择了控制台示例，这样我们就可以避免在窗口环境中创建和显示窗口时产生的所有无关代码。要查看任何特定示例的输出，您可以在`_pmain`函数末尾的`return`语句上设置断点，然后使用 Visual Studio 调试器运行它，或者您可以使用 Visual Studio 中**调试**菜单中的**启动而不调试**命令运行它(通常使用 Ctrl+F5 键盘快捷键)。您还需要确保您希望运行的项目被设置为启动项目。您可以通过在解决方案资源管理器中右键单击项目名称，然后在出现的上下文菜单中左键单击**设置为启动项目**来完成此操作。

## C++ 11

2011 年，负责设计和开发 C++ 作为一种语言的 ISO/IEC 工作组采用了新的主要版本的 C++ 语言标准。与 C++ 98 和 C++ 03 相比，C++ 11 感觉像是不同的语言。因为 C++ 11 太新了，所以没有支持每一个特性的编译器，有些编译器支持的功能比其他编译器少。我已经瞄准了 Visual C++ 及其在最新版本中实现的功能(在撰写本文时是 Visual Studio 2012 RC)，尽管我提到了一些 Visual C++ 目前不支持的功能，并在适当的时候指出了这一点。

Visual C++ 在 Visual Studio 2012 RC 和 Visual Studio 2012 RTM 之间的变化不大。有计划在 RTM 发布后的某个时间进行带外更新，这将增加额外的 C++ 11 语言支持。由于我无法预测哪些功能将被添加，也没有任何关于它的内部知识，所以我基本上没有涵盖 RC 中不支持的内容。

如果你有五年前或者更久以前的 C++ 经验，你可能会非常惊喜——这并不是说它拥有 C# 所拥有的一切。

C# 和有一些特性。我在 C++ 工作时怀念的. NET。但是在 C# 中工作时，我也错过了 C++ 的一些特性。当我在 C++ 中工作时，我怀念 CLR 的类型系统提供的 C# 中的简单转换。我也想念。NET 更完整的异常集和更好的智能感知。NET 提供的。在 C++ 中，我发现自己比在 C# 中更多地参考文档来弄清楚什么样的参数值可以并且应该传递给某个特定的函数，以及期望从它那里得到什么样的值。

当我在 C# 中工作时，我发现自己错过了 C++ 不同的存储持续时间所提供的广度。在 C# 中，大部分事情都是在 GC 管理的堆上结束的，这大大简化了内存管理。但是有时我不一定希望类实例在堆上。在 C# 中，我别无选择，只能将类重写为结构；而在 C++ 中，我可以轻松地在两者之间进行选择，而不需要更改类定义本身。我也想念独立的函数(尽管它们可以用 C# 中静态类的静态方法来模拟)。我也喜欢我的 C++ 程序在我编译它们时最终成为高度优化的(因此很难理解的)机器代码，所以如果我想让我的代码保密(就像我使用的那样)，我真的不需要担心试图混淆我的程序。NET，尽管有一些非常好的混淆工具)。

每种语言都有自己的问题，也有自己的历史和怪癖。希望您会发现 C++ 是一种有趣且有用的语言，可以添加到您的编程曲目中。