查看这样的代码(添加评论):
std::string some_var;
std::string some_func(); // both are defined, but definition is irrelevant
...
return "some text " + some_var + "c" + some_func(); // intentionally "c" not 'c'
我想知道, operator +
std::string
必须复制(在使用复制构造/赋值的意义上,而不是复制的内部缓冲区,例如SSO)适用),以及实际复制的内容。快速查看cppreference只是部分有用,因为它列出了12个(!)不同的案例。在某种程度上,我要求确认我对该页面的理解:
char/const char*
参数构造临时字符串,然后在案例1中得到结果char/const char*
参数,然后导致案例6)或7)insert/append
进行变异,如果提供了char/const char*
参数,则由于过载而不需要临时值insert/append
。在所有情况下,返回r值以便于进一步链接。没有复制(除了要在插入位置附加/插入的参数的副本)。可能需要移动字符串的内容。如上例所示的链应该因此导致:2) - > 6) - > 11) - > 8),没有任何lhs的副本,只是修改了第一次操作(创建临时字符串)产生的r值的缓冲区。
因此,一旦operator +=
至少使用r值参数,这似乎与operator +
一样有效。这是正确的吗?在C ++ 11中使用operator +=
而不是operator +
之后是否有任何意义,除非两个参数都是l值字符串?
编译器还可以进行哪些优化?
编辑:澄清问题的意图。初始部分仅涉及语言的细节(实施不具备);最后一个问题是关于其他优化。
答案 0 :(得分:0)
字符串是一个相当不透明的对象:它包含一个内部字符缓冲区并按照它想要的方式管理它。向字符串添加单个字符可能会在分配新缓冲区,初始部分的副本和添加部分的副本时结束。全部取决于分配的缓冲区是否足够大以接受添加的部分。
报价说:
...没有复制(除了要在插入位置附加/插入的参数的副本)。 可能需要移动字符串的内容。
不同地说新的分配,旧缓冲区的完整拷贝和释放......
当你谈到效率和优化时,你必须记住编译器不必遵循你编写程序的方式。由于 as-if 规则,只要遵守可观察的行为,它就可以优化所需的方式。 C ++标准说:
1.9程序执行[intro.execution]
...
5执行格式良好的程序的符合实现应产生相同的可观察行为 作为具有相同程序的抽象机的相应实例的可能执行之一 和相同的输入。
注意事项甚至解释了:
实施可以自由地忽略对此的任何要求 国际标准,只要结果就好像已经遵守了要求,只要可以从中确定 程序的可观察行为。
因此,a = a + b;
和a += b;
可能在完全相同的代码中编译。
编写C ++程序时,不应该担心低级优化:编译器会关心它,并且通常认为编译器比你更聪明。只有在确定了真正的瓶颈时才这样做,并且如果仅针对一个架构和一个配置上的一个编译器,请注意低级优化。