为什么C++;初始分配比C'大得多;s 使用相同的代码时,只需将编译器(从C编译器转换为C++编译器)将改变分配多少内存。我不太清楚这是为什么,我想了解更多。到目前为止,我所得到的最好的回答是“可能是I/O流”,这不是很有描述性的,它让我想知道“你不为你不使用的东西付费”的C++方面。

为什么C++;初始分配比C'大得多;s 使用相同的代码时,只需将编译器(从C编译器转换为C++编译器)将改变分配多少内存。我不太清楚这是为什么,我想了解更多。到目前为止,我所得到的最好的回答是“可能是I/O流”,这不是很有描述性的,它让我想知道“你不为你不使用的东西付费”的C++方面。,c++,c,benchmarking,C++,C,Benchmarking,我使用的是Clang和GCC编译器,分别是7.0.1-8和8.3.0-6版本。我的系统运行的是Debian10(Buster),最新版本。通过Valgrind Massif进行基准测试 #include <stdio.h> int main() { printf("Hello, world!\n"); return 0; } 对于Valgrind,我在每个编译器和语言上运行Valgrind--tool=massif--massif out file=m_compi

我使用的是Clang和GCC编译器,分别是7.0.1-8和8.3.0-6版本。我的系统运行的是Debian10(Buster),最新版本。通过Valgrind Massif进行基准测试

#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}
对于Valgrind,我在每个编译器和语言上运行
Valgrind--tool=massif--massif out file=m_compiler_lang./compiler lang
,然后运行
ms_print
来显示峰值


<我在这里做了什么错误?

堆使用来自C++标准库。它为启动时的内部库使用分配内存。如果你不链接它,C和C++版本之间应该是零差值。使用GCC和Clang,您可以使用以下工具编译文件:

g++ -Wl,--as-needed main.cpp g++-Wl,--根据需要main.cpp 这将指示链接器不要链接未使用的库。在示例代码中,不使用C++库,因此它不应该链接到C++标准库。

您还可以使用C文件来测试这一点。如果使用以下工具进行编译:

gcc main.c -lstdc++ gcc main.c-lstdc++ 堆使用情况将再次出现,即使您已经构建了一个C程序

堆使用显然取决于使用的特定C++库实现。在你的情况下,这是GNU C++库。其他实现可能不会分配相同数量的内存,或者它们根本不会分配任何内存(至少在启动时不可能)。例如,LLVM C++库()在启动时不进行堆分配,至少在我的Linux机上:

clang++ -stdlib=libc++ main.cpp clang++-stdlib=libc++main.cpp 堆的使用与根本不针对它进行链接是一样的


(如果编译失败,则可能未安装libc++。包名通常包含“libc++”或“libcxx”。

GCC和Clang都不是编译器,它们实际上是工具链驱动程序。这意味着它们调用编译器、汇编程序和链接器

<>如果你用C或C++编译器编译你的代码,你会得到相同的程序集。汇编程序将生成相同的对象。不同之处在于,工具链驱动程序将为两种不同语言的链接器提供不同的输入:不同的初创公司(C++需要在命名空间级别上为静态或线程本地存储持续时间的对象执行构造函数和析构函数代码,并且需要堆栈框架的基础结构来支持异常处理过程中的展开),C++标准库(也有命名空间级别的静态存储持续时间对象),可能还有其他运行时库(例如,libgcc及其堆栈展开基础结构)

简而言之,编译器不是导致内存占用增加的原因,而是选择C++语言所使用的东西的链接。
<> Pc>确实,C++有“只为你所用的”哲学,但是通过使用语言,你可以为它付出代价。你可以禁用语言的部分(RTTI,异常处理),但是你不再使用C++了。正如另一个答案中所提到的,如果你根本不使用标准库,你可以指示驱动程序把它排除在外。(-Wl,--根据需要)但是如果你不使用C++的任何特性或者它的库,为什么你甚至选择C++作为一种编程语言?< /P>首先,你是如何构建的?你使用什么选项?你如何测量?你如何运行Valgrind?如果我没记错的话,现代C++编译器必须有一个没有性能H的异常模型。要进入<代码>尝试块,但代价是内存占用较大,可能是用跳转表或其他东西。也许尝试编译没有例外,看看它有什么影响。编辑:实际上,反复尝试禁用各种C++特性,看看它对内存占用有什么影响。e> 而不是
clang
,相同的分配在那里,这强烈表明它是由于链接libraries@bigwillydos这确实是C++,我没有看到C++规范中的任何一部分,除了潜在地包括STdio.h而不是CSTDIO之外,但至少在旧的C++版本中是允许的。这个程序中的“格式错误”?我发现那些gcc和clang编译器在
C
模式下生成的字节数与
C++
模式下生成的字节数完全相同,这很可疑。你有没有犯下转录错误?看到这个答案,我的第一个想法是如果这个标志有助于减少不必要的开销,为什么默认情况下不打开它?”。有一个好的答案吗?@Nat我猜在开发时编译会比较慢。当你准备创建一个发布版本时,你会打开它。同样,在一个普通/大型的代码库中,差异可能是最小的(如果你正在使用大量的STD库等)@在
-Wl,--as-needed
标志中删除您在
-l
标志中指定的库,但您没有实际使用。因此,如果您不使用库,则不要链接它。您不需要此标志。但是,如果您的构建系统添加了太多库,则需要进行大量的清理工作只需链接所需的符号,就可以使用此标志。不过,标准库是一个例外,因为它是自动链接的。所以这是一个极端情况。@Nat--根据需要可能会产生不必要的副作用,它的工作原理是检查是否使用库的任何符号,并将未通过测试的符号踢出。但是:库也可以执行v如果你在库中有一个静态C++实例,那么隐含的东西就隐含了。 gcc main.c -lstdc++ clang++ -stdlib=libc++ main.cpp