/Zc:throwingNew(假定运算符执行新的引发操作)
指定 /Zc:throwingNew 选项时,编译器将优化 operator new
调用以跳过空指针返回检查。 此选项使编译器假定所有链接的 operator new
实现和自定义分配器都符合 C++ 标准,并在分配失败时引发操作。 默认情况下,在 Visual Studio 中,编译器悲观地为这些调用生成 null 检查 (/Zc:throwingNew-),因为用户可以链接到非引发 operator new
实现或编写可返回空指针的自定义分配器例程。
语法
/Zc:throwingNew[-]
注解
由于 ISO C++98 标准已指定默认 operator new 在内存分配失败时引发 std::bad_alloc
, Visual Studio 6.0 及先前版本的 Visual C++ 版本在分配失败时都会返回空指针。 从 Visual Studio 2002 开始,operator new
符合标准并在失败时引发操作。 为了支持使用较早分配样式的代码,Visual Studio 在 nothrownew.obj 中提供了可链接的 operator new
的实现,以便在失败时返回空指针。 默认情况下,编译器还会生成防御 null 检查,以防止这些较早样式的分配器在失败时立即崩溃。 /Zc:throwingNew 选项使编译器在所有链接的内存分配器都符合标准的情况下不进行这些 null 检查。 这不适用于显式非引发 operator new
重载,这些重载通过类型 std::nothrow_t
的其他参数进行声明且具有显式 noexcept
规范。
从概念上讲,为在免费存储中创建对象,编译器会生成代码以分配其内存,然后调用其构造函数来初始化内存。 由于 MSVC 编译器通常无法判断此代码是否会链接到不符合标准且非引发的分配器,因此默认情况下,它还会在调用构造函数之前生成 null 检查。 如果非引发分配失败,这可以防止调用构造函数时发生空指针取消引用。 在大多数情况下,这些并非必要检查,因为默认 operator new
分配器会引发操作,而不会返回空指针。 这些检查也会产生不良影响。 它们会膨胀代码,填满分支预测器,并抑制其他有用的编译器优化,例如初始化对象的去虚拟化或常量传播。 这些检查只是为了支持链接到 nothrownew.obj 或具有自定义不符合标准的 operator new
实现的代码。 如果不使用不符合标准的 operator new
,则建议使用 /Zc:throwingNew 来优化代码。
/Zc:throwingNew 选项默认处于禁用状态,并且不受 /permissive- 选项的影响。
如果使用链接时间代码生成 (LTCG) 进行编译,则无需指定 /Zc:throwingNew。 使用 LTCG 编译代码时,编译器可以检测是否使用了默认的、符合标准的 operator new
实现。 如果是,编译器会自动忽略 null 检查。 链接器会查找 /ThrowingNew 标志,以判断 operator new
实现是否符合标准。 通过在自定义 operator new 实现的源中添加此指令,可以向链接器指定此标志:
#pragma comment(linker, "/ThrowingNew")
有关 Visual C++ 中一致性问题的详细信息,请参阅 Nonstandard Behavior。
在 Visual Studio 开发环境中设置此编译器选项
打开项目的“属性页” 对话框。 有关详细信息,请参阅在 Visual Studio 中设置 C++ 编译器和生成属性。
从“配置”下拉菜单中,选择“所有配置”。
选择“配置属性”>“C/C++”>“命令行”属性页。
修改“附加选项”属性以包含 /Zc:throwingNew 或 /Zc:throwingNew-,然后选择“确定”。
另请参阅
MSVC 编译器选项
MSVC 编译器命令行语法
/Zc(一致性)
noexcept (C++)
异常规范 (throw) (C++)
终止(异常)