为什么使用C++;与at()或索引相比,迭代器大幅增加了代码大小? 我一直在研究使用嵌入式系统上的迭代器(16kb的SRAM和64 KB的Flash、皮质M4)等新的C++语言特性,并遇到了一个令人惊讶的障碍。迭代器究竟为什么如此巨大?我的印象是,它们基本上是一些指针算术或索引。STL是否引入了一些意外的代码

为什么使用C++;与at()或索引相比,迭代器大幅增加了代码大小? 我一直在研究使用嵌入式系统上的迭代器(16kb的SRAM和64 KB的Flash、皮质M4)等新的C++语言特性,并遇到了一个令人惊讶的障碍。迭代器究竟为什么如此巨大?我的印象是,它们基本上是一些指针算术或索引。STL是否引入了一些意外的代码,c++,gcc,stl,iterator,embedded,C++,Gcc,Stl,Iterator,Embedded,这些是在windows上使用Kinetis Design Studio和gcc-arm-none-eabi-4_9工具链,而不是使用以下标志 arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fsingle-precision-constant -

这些是在windows上使用Kinetis Design Studio和gcc-arm-none-eabi-4_9工具链,而不是使用以下标志

arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Os -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fsingle-precision-constant -flto  -g3 -I"../Sources" -I"../Includes" -std=gnu++11 -fabi-version=0 -std=c++11 -MMD -MP -MF"Sources/System.d" -MT"Sources/System.o" -c -o "Sources/System.o" "../Sources/System.cpp"
ITM_SendChar只需要一个字符并将其放入寄存器

std::string input = "Oh hai there! :D\n";

#ifdef char_array
    // .text              7352
    // .data               376
    // .bss                236
    for(int i = 0; i < input.size(); i++)
            ITM_SendChar(input[i]);
#endif

#ifdef char_at
    // .text              7392
    // .data               376
    // .bss                236
    for(int i = 0; i < input.size(); i++)
        ITM_SendChar(input.at(i));
#endif

#ifdef char_itterator
    // .text             39744        
    // .data               384   
    // .bss                252   
    for(char some_char : input)
        ITM_SendChar(some_char);
#endif

#ifdef char_itterator_auto
    // .text             39744        
    // .data               384   
    // .bss                252   
    for(auto some_char : input)
        ITM_SendChar(some_char);
#endif

#ifdef char_itterator_auto_no_copy
    // .text             39744        
    // .data               384   
    // .bss                252   
    for(auto& some_char : input)
        ITM_SendChar(some_char);
#endif
std::string input=“Oh hai!:D\n”;
#ifdef字符数组
//.文本7352
//.数据376
//.bss 236
对于(int i=0;i
[]运算符和.at()之间的主要区别在于.at()执行边界检查,如果索引超出边界,则会引发异常

在使用迭代器时,您正在使用的标准库实现似乎是在为某些内容链接额外的代码。找到原因的唯一方法是检查两个版本的链接器映射文件,并仔细查看正在使用的函数的源代码,可能还有生成的程序集

一般来说,如果您需要非常小的代码,您希望避免使用任何标准库,因为其中的函数可以通过它们引入大量代码和数据。即使是将命令行解析为main()所期望的格式的代码也可能非常庞大

要进行比较,请尝试以下方法:

const char *input = "Oh hai there! :D\n";

while (*input)
        ITM_SendChar(*input++);

一个(或两个)C++标准,用指针实现迭代器是合法的。(你可以通过谷歌搜索标准中的“removed weasel Worming”来了解更多信息。)较新的标准需要更多的迭代器,例如,如果在相同类型的两个容器中有两个对应的迭代器,那么交换这两个容器也需要交换这两个迭代器(如果您愿意,请参阅N4527 23.2.1脚注9自行阅读)。所有这一切都意味着使用索引而不是迭代器索引到容器中肯定会更有效。只是并非所有标准容器类型都支持这样做…这也是使用迭代器增加代码大小的原因。

您是否在某些调试配置中编译?我不知道您的构建环境,但是,例如。,在Visual C++的调试配置中,各种检查都已完成。首先,您应该对苹果进行比较,而不是在基于范围的for循环中进行复制。如果使用
auto&some_char:input
,会发生什么情况?感谢@NathanOliver的建议,但没有任何更改。我将结果添加到了我的问题中。JohnB还有-g3标志for调试但删除它没有任何区别。据我所知,KDS在调试时不包含任何额外内容。您可能需要问问自己,在这样一个资源受限的环境中使用STL是否合适(通常不是!)。在您的平台上,将自己限制在避免模板和“隐藏”的子集可能是合适的动态内存分配-这意味着没有STL和NO.Cudith:STD::String 。在小目标上使用C++的答案可能是有用的。@克利福德:模板是纯编译器的东西。在运行时,没有区分<代码> f>(<)/>代码> <代码> fyTin()。,您刚才展示的内容在代码大小方面也完全足够了,谢谢。我只是希望了解embedded的迭代器魔力,因为它看起来非常有用,并且由于我了解迭代器的工作方式,对代码大小的影响最小,但遗憾的是,这似乎是不可能的。我将研究链接器映射文件稍后,看看我是否能找出问题所在,是否有任何解决方法,以便我仍然可以使用迭代器,而不必让所有的flash都像渡渡鸟一样。@hak8or-“您刚才展示的代码大小也完全足够了…”你经常使用<代码> CXXFLAG++-FFUNTUCTION部分-FDATA部分和 LDFLAG++= Wl,GC段< /code >以减小代码大小。但是这与“为什么使用C++迭代器比AT-(或)索引代码大小增加得更大?”和“为什么在迭代中,迭代器如此庞大?”是一个不同的问题。