Oracle® Developer Studio 12.5:C++ 用户指南

退出打印视图

更新时间: 2016 年 7 月
 
 

11.7 替换 C++ 标准库

替换与编译器一起发布的标准库是有风险的,不能保证产生预期的结果。基本操作是禁用编译器提供的标准头文件和库,指定找到新的头文件和库(及库本身的名称)的目录。

编译器支持标准库的 STLport 和 Apache stdcxx 实现。有关更多信息,请参见STLportApache stdcxx 标准库

替换 C++ 标准库的讨论仅适用于缺省 -compat=5 模式。

11.7.1 可以替换的内容

可以替换大多数标准库及其关联头文件。 替换的库是 libCstd,关联的头文件如下所示:

<algorithm> <bitset> <complex> <deque> <fstream <functional> <iomanip> <ios> <iosfwd> <iostream> <istream> <iterator> <limits> <list> <locale> <map> <memory> <numeric> <ostream> <queue> <set> <sstream> <stack> <stdexcept> <streambuf> <string> <strstream> <utility> <valarray> <vector>

库的可替换部分由一般称为 "STL" 的内容和字符串类、iostream 类及其帮助类组成。因为这些类和头文件是相互依赖的,所以不能仅替换其中的一部分。如果要替换任何一部分,就应该替换所有头文件和所有 libCstd

11.7.2 不可替换的内容

标准头文件 <exception><new><typeinfo> 与编译器本身以及 libCrun 紧密相关,不能可靠替换。库 libCrun 包含了编译器依赖且不能替换的许多“帮助”函数。

从 C 继承的 17 个标准头文件(<stdlib.h><stdio.h><string.h> 等)与 Oracle Solaris 操作系统和 Oracle Solaris 基本运行时库 libc 紧密相关,不能可靠地替换。这些头文件的 C++ 版本(<cstdlib><cstdio><cstring> 等)与基本 C 版本紧密相关,不能可靠替换。

11.7.3 安装替换库

要安装替换库,必须先确定替换头文件的位置和 libCstd 的替换库。为方便讨论,假定头文件放置在 /opt/mycstd/include 中,库放置在 /opt/mycstd/lib 中。假定库称为 libmyCstd.a。(通常,库名称以 "lib" 开头。)

11.7.4 使用替换库

每次编译时,都使用 -I 选项指向头文件的安装位置。此外,还使用 -library=no%Cstd 选项防止查找编译器自身版本的 libCstd 头文件。例如:

example% CC -I/opt/mycstd/include -library=no%Cstd... (compile)

编译期间,-library=no%Cstd 选项防止搜索编译器自身版本的这些头文件所在的目录。

每次执行程序或库链接时,都使用 -library=no%Cstd 选项防止查找编译器自身的 libCstd,使用 -L 选项指向替换库所在的目录,以及使用 -l 选项指定替换库。例如:

example% CC -library=no%Cstd -L/opt/mycstd/lib -lmyCstd... (link)

也可以直接使用库的全路径名,而不使用 -L-l 选项。例如:

example% CC -library=no%Cstd /opt/mycstd/lib/libmyCstd.a... (link)

链接期间,-library=no%Cstd 选项防止链接编译器自身版本的 libCstd

11.7.5 标准头文件实现

C 有 17 个标准头文件(<stdio.h><string.h><stdlib.h> 等)。这些头文件作为 Oracle Solaris 操作系统的一部分提供,位于 /usr/include 目录中。C++ 也有这些头文件,但另外要求在全局名称空间和 std 名称空间中都有各种声明的名称。

C++ 也有另一个版本的各个 C 标准头文件(<cstdio><cstring><cstdlib> 等),仅名称空间 std 中有各种声明的名称。最后,C++ 添加了 32 个自己的标准头文件(<string><utility><iostream> 等)。

标准头文件的明显实现将 C++ 源码中找到的名称用作包括的文本文件的名称。例如,标准头文件 <string>(或 <string.h>)可能指某目录中名为 string(或 string.h)的文件。这种明显实现有以下缺点:

  • 如果头文件没有文件名后缀,则无法仅搜索头文件或为头文件创建 makefile 规则。

  • 如果具有名为 string 的目录或可执行程序,可能会错误地找到该目录或程序而不是标准头文件。

为了解决这些问题,编译器 include 目录会包含一个与头文件同名的文件和一个指向它且具有唯一后缀 .SUNWCChSUNW 是所有编译器相关软件包的前缀,CC 指 C++ 编译器,h 是常用的头文件后缀)的符号链接。 指定 <string> 后,编译器将其重写为 <string.SUNWCCh> 并搜索该名称。后缀名只能在编译器自己的 include 目录中找到。如果这样找到的文件是符号链接(正常情况下),编译器就对链接进行一次引用解除,并将结果(此例中是 string)用作错误消息和调试器引用的文件名。忽略文件的依赖性信息时,编译器使用带后缀的名称。

仅当出现在尖括号中且无需指定任何路径时,17 种标准 C 头文件和 32 种标准 C++ 头文件的两种格式才会发生名称重写。如果使用引号来代替尖括号指定任何路径组件或其他某些头文件,就不会有重写发生。

下表说明了通常的情况。

表 25  头文件搜索示例
源代码
编译器搜索
注释
<string>
string.SUNWCCh
C++ 字符串模板
<cstring>
cstring.SUNWCCh
C string.h 的 C++ 版本
<string.h>
string.h.SUNWCCh
C string.h
<fcntl.h>
fcntl.h
不是标准 C 或 C++ 头文件
"string"
string
双引号,不是尖括号
<../string>
../string
指定的路径

如果编译器未找到 header.SUNWCCh,则编译器将重新搜索 #include 指令中提供的名称。例如,如果使用指令 #include <string>,编译器就尝试查找名为 string.SUNWCCh 的文件。如果搜索失败,编译器就查找名为 string 的文件。

11.7.5.1 替换标准 C++ 头文件

由于标准头文件实现中介绍的搜索算法,您无需提供Installing the Replacement Library中介绍的安装替换库版本的替换头文件。但是,如果遇到了所描述的某些问题,建议为每个无后缀的头文件添加后缀为 .SUNWCCh 的符号链接。也就是说,对于文件 utility,可以运行以下命令:

example% ln -s utility utility.SUNWCCh

编译器第一次查找 utility.SUNWCCh 时,会找到它,而不会和其他名为 utility 的文件或目录混淆。

11.7.5.2 替换标准 C 头文件

不支持替换标准 C 头文件。如果仍然希望提供标准头文件的自己的版本,那么建议按以下步骤操作:

  • 将所有替换头文件放置在一个目录中。

  • 在该目录中创建指向每个替换头文件的 .SUNWCCh 符号链接。

  • 在每次调用编译器时使用 -I 指令,搜索包含替换头文件的目录。

例如,假设有 <stdio.h><cstdio> 的替换。请将文件 stdio.hcstdio 放在目录 /myproject/myhdr 中。在该目录中,运行以下命令:

example% ln -s stdio.h stdio.h.SUNWCCh
example% ln -s cstdio cstdio.SUNWCCh

每次编译时使用 -I/myproject/mydir 选项。

警告信息:
  • 如果要替换任何 C 头文件,就必须成对替换。例如,如果替换 <time.h>,还应该替换 <ctime>

  • 替换头文件必须与被替换版本具有相同的效果。也就是说,各种运行时库(如 libCrunlibClibCstdlibc)是使用标准头文件中的定义生成的。如果替换文件不匹配,那么程序不能工作。