简体   繁体   English

与at()或索引相比,为什么使用C ++迭代器会大大增加代码大小?

[英]Why does using C++ iterators increase code size drastically compared to at() or indexing?

I have been looking at using the newer C++ language features such as iterators on embedded systems (16KB of SRAM and 64 KB of flash, Cortex M4) and hit a surprising roadblock. 我一直在考虑使用更新的C ++语言功能,例如嵌入式系统上的迭代器(16KB SRAM和64KB闪存,Cortex M4),并遇到了令人惊讶的障碍。 Why on earth are iterators so monstrously large? 为什么地球上的迭代器如此之大? I was under the impression they are basically some pointer arithmetic or indexing. 我对它们的印象基本上是某种指针算术或索引。 Is the STL pulling in some unexpected code? STL是否引入了一些意外的代码?

These are using Kinetis Design Studio on windows with the gcc-arm-none-eabi-4_9 toolchain from here using the following flags. 这些都是从GCC-臂无- EABI-4_9工具链窗口使用的Kinetis设计工作室在这里使用了以下标志。

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 just takes a single char and puts it in a register. 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

The main difference between the [] operator and .at() is that .at() does bounds checking, and will throw an exception if the index is out of bounds. []运算符和.at()之间的主要区别是.at()会进行边界检查,如果索引超出范围,则会抛出异常。

It seems likely that the standard library implementation you're using is linking in extra code for something when using an iterator. 您正在使用的标准库实现似乎在使用迭代器时链接了一些额外的代码。 The only way to find the cause is to examine the linker map file for both versions, and look closely at source code for the functions you're using, and maybe the generated assembly too. 找出原因的唯一方法是检查两个版本的链接器映射文件,并仔细查看所使用功能的源代码,以及生成的程序集。

In general, if you need your code to be very small you want to avoid using any of the standard library, because the functions in there can pull in lots of code and data with them. 通常,如果您需要代码非常小,则要避免使用任何标准库,因为其中的功能会随其引入大量代码和数据。 Even the code that parses the command line into the format that main() expects can be quite big. 甚至将命令行解析成main()期望格式的代码也可能很大。

For comparison, try this: 为了进行比较,请尝试以下操作:

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

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

One (or two) C++ standards ago it was legal for iterators to be implemented with pointers. 一(或两个)C ++标准之前,使用指针实现迭代器是合法的。 (You can google "removed weasel wording" in the standard to find out more about this.) Newer standards require more from iterators, for example that if you have two corresponding iterators in two containers of the same type, then swapping those two containers also requires swapping those two iterators (see N4527 23.2.1 footnote 9 to read it for yourself, if you like). (您可以在标准中用Google删除“鼬鼠措辞”以了解更多信息。)较新的标准需要迭代器提供更多信息,例如,如果您在两个相同类型的容器中有两个相应的迭代器,则还要交换这两个容器需要交换这两个迭代器(如果需要,请参阅N4527 23.2.1脚注9自行阅读)。 All of this means that indexing into a container with indexes instead of iterators can certainly be more efficient. 所有这些都意味着使用索引而不是迭代器索引到容器中肯定可以提高效率。 It's just that that isn't supported for all standard container types... And that's also why using iterators increases code size. 只是所有标准容器类型均不支持该功能...这也是为什么使用迭代器会增加代码大小的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Microblaze &amp; C++ | 为什么在某些条件下代码大小会急剧增加? - Microblaze & C++ | Why does the code size increase dramatically under certain conditions? 为什么添加虚拟方法会增加C ++中的类大小? - Why does adding virtual method increase class size in C++? C ++流和迭代器:为什么只打印一次? - C++ streams and iterators: Why does this only print once? 为什么 Microsoft Visual C++ 库实现“解包”迭代器? - Why does theMicrosoft Visual C++ library implementation 'unwrap' iterators? 为什么此C ++代码比C#变体慢 - why this C++ code is slower compared to C# variant 如果与基类相比没有新的成员变量,C++ 是否允许增加派生类的大小? - Is C++ allowed to increase the derived class size if there're no new member variables compared to the base class? 与 Java 和 Python 相比,为什么每次使用 Cmake 运行 C++ 程序都需要这么长时间? - Why does running a C++ program using Cmake takes so long each time compared to Java and Python? 为什么生成 pdb 文件会增加我的原生 C++ exe 的大小? - Why does generating pdb files increase the size of my native C++ exe? 使用 printf 和 C++ 迭代器 - using printf with C++ iterators 与java相比,为什么这个C ++代码执行速度如此之慢? - Why is this C++ code execution so slow compared to java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM