我一直在寻找使用更新的C ++语言功能,例如嵌入式系统上的迭代器(16KB的SRAM和64 KB的闪存,Cortex M4),并遇到了令人惊讶的障碍。为什么地球上的迭代器如此庞大?我的印象是他们基本上是一些指针算术或索引。 STL会引入一些意想不到的代码吗?
这些是在Windows上使用Kinetis Design Studio,使用here中的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
答案 0 :(得分:3)
[]运算符和.at()之间的主要区别在于.at()会进行边界检查,如果索引超出范围,则会抛出异常。
使用迭代器时,您正在使用的标准库实现似乎是在链接额外的代码。找到原因的唯一方法是检查两个版本的链接器映射文件,并仔细查看您正在使用的函数的源代码,以及生成的程序集。
通常,如果您需要的代码非常小,则需要避免使用任何标准库,因为其中的函数可以使用它们提取大量代码和数据。即使将命令行解析为main()期望的格式的代码也可能非常大。
为了比较,试试这个:
const char *input = "Oh hai there! :D\n";
while (*input)
ITM_SendChar(*input++);
答案 1 :(得分:1)
之前的一个(或两个)C ++标准,使用指针实现迭代器是合法的。 (您可以在标准中谷歌“删除weasel措辞”以了解更多相关内容。)较新的标准需要更多来自迭代器,例如,如果您在两个相同类型的容器中有两个相应的迭代器,那么也交换这两个容器需要交换这两个迭代器(如果你愿意,请参阅N4527 23.2.1脚注9自己阅读)。所有这些意味着索引到具有索引而不是迭代器的容器当然可以更有效。只是所有标准容器类型都不支持...这也是使用迭代器增加代码大小的原因。