- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在this Stack Overflow question (不幸的是,自从我开始研究这个问题以来,这个问题就被搁置了),有几个人提到“在现代 C++ 中”,由于移动语义,编译后的代码不需要为操作复制字符串 string = string + s1
,给人的印象是使用现代 C++ 编译器,string = string + s1
可以和 string += s1
一样高效。我发现这种说法很可疑,但我在 C++03 的遗留世界中工作,仍然对移动语义知之甚少。 (这是我的工作,我不选择我们的编译器。)
string += s1
的成本使用操作string += s1
,除非string
的缓冲区扩展超过其先前分配的容量,否则不需要新的分配,并且假设合理实现string 类,在 string += s1
操作中不会创建临时对象。假设结果的大小符合先前分配的容量,string += s1
中成本最高的部分是将 s1
的内容附加(复制)到末尾string
的原始内容使用先前分配但未使用的空间。另请注意,该复制操作的成本只是 s1
的字节数,而不是总字节数。
string = string + s1
的成本在旧版 C++(03 及更早版本)中,string = string + s1
据我所知,至少需要一次临时分配(用于评估 string + s1
), 以及s1
和原始string
中字节数之和的两份完整拷贝(1.复制的原始内容code>string
到临时文件并将 s1
的字节复制附加到临时文件中那些字节的末尾,然后 2. 复制所有的从临时返回到 string
缓冲区的结果字节,包括无论如何已经存在的原始内容的字节)。显然,这比上面描述的 string += 1
的成本要昂贵得多,并且它可能会产生显着差异,特别是如果在循环中多次执行追加操作(它是 Shlemiel the painter algorithm ,除了它甚至比 strcat()
的低效率还要糟糕!)。
string = string + s1
的成本在我看来,表达式 string + s1
的计算将产生一个右值,随后可以将其作为对 string
的移动赋值的右值引用提供运算符,无需将 string + s1
的结果复制回 string
。但这并不能消除创建原始临时对象以及相关联的复制的需要,不是吗?在我看来,移动语义所能做的最好的事情就是消除两个完整复制操作之一。仍然需要一次分配和一次复制操作(以创建临时文件),对吗?如果是这样,那么移动语义只会使这样的代码“不那么糟糕”,它不会阻止它成为 Shlemiel the painter algorithm 的另一个实例。 ,而且比C的strcat()还差!
请告诉我我错了。 另外:请不要猜测。那没有用。如果您的回答或评论以“我认为...”开头,请不要提交。
最佳答案
One allocation and one copy operation (to create the temporary) is still required, right? If so, then move semantics only makes code like that "less bad"
据我所知,你是对的。移动语义并没有消除这个例子中的所有开销,只是一些。
如果string
没有足够的容量,那么就无法避免所有字符的重新分配和复制。但是,如果有足够的容量,为了获得最佳性能,无论标准版本如何,您应该做的是:
string.append(s1); // this
string += s1; // or this
如果容量足够,则不会发生重新分配,并且不会复制原始 string
的字符。与 strcat
相同。与 strcat
不同,如果容量不足,行为是明确定义的。
在循环中进行时,理想情况下应在循环之前预留全部容量。如果无法知道结果长度,那么有一个潜在的问题:据我所知,标准没有指定 append 的容量增长策略。如果它做几何增长,那么带有追加的简单循环是好的。如果它只分配完全相同的旧长度 + 追加长度而没有空间开销,那么琐碎的追加循环将导致在每次迭代中都进行分配。
我测试了libstdc++,它呈几何级数增长。如果您偏执,那么为了保证这一点,您在技术上需要明确检查每次迭代是否会发生重新分配,并保留几何增长的内存量:
// paranoid mode: enabled
int growth_rate = 2;
for(auto& s1 : range) {
auto new_size = string.size() + s1.size();
auto new_cap = string.capacity();
while (new_cap < new_size)
new_cap *= growth_rate;
string.reserve(new_cap);
string += s1;
}
然而,在这种特殊情况下,std::ostringstream
可能更简单。
关于c++ - 有多少复制操作可以在 'string=string+s1' 和 'string+=s1' 之间移动语义保存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57151379/
我正在尝试提升我的 javascript 编程技能(或者说我的编程技能时期 :)) 所以我试图理解一些语义: 第一行的“?”是什么意思?均值和“-distance”中的减号 第二行中的“+=”或“-=
我正在尝试在语义 UI 中执行复选框,但它不起作用,我无法弄清楚我做错了什么。 我包括jquery、semantic.min.js、checkbox.js 和semantic.min.css,然后我添
我正在构建一个 Spring 后端。我有一个 Controller ,它获取一个“搜索对象” - 一个具有 10 个字段的对象,其中只有一个应该被填充,所以搜索功能(我没有编写,但需要对其进行更改和重
我面临着编写更智能/高级的“相关内容”算法的挑战,并且不知道从哪里开始,所以我决定提出一个问题,是否有人会指出我正确的方向。 我们的数据库包含很多文章,到目前为止,我们使用关键字/标签查询了相关文章,
我正在尝试将通用字符串写入Rust中的数字函数,其中支持的类型为i16,i32,i64,u32,u64,f32和f64。 最初我有这个: fn str_to_num(s: &str, default_
假设我们在 hpp 文件中有一个带有唯一指针的简单结构: struct SomeType { SomeType() = default; ~SomeType(); st
这是同一预处理指令的多个问题。 1 - <> 还是 ""? 除了在 MSDN 中找到的信息: #include Directive (C-C++) 1.a:这两种符号有什么区别? 1.b:所有编译器都
所以基本上我有一个带有列表的简单系统,当我选择一个项目时,它会显示描述和绑定(bind)到该项目的图像。 项目:https://jsfiddle.net/jhnjcddh/2/ 问题是我需要在 JS
很抱歉问了一个愚蠢的问题,但有人能告诉我以下是什么意思吗 for ctype, (codename, name) in searched_perms: 我不明白括号里是怎么回事。 for ctype
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Why do all these crazy function pointer definitions al
我正在学习 HTML5,并获得了一个将 CSS Zen Gardens 转换为 HTML5 语义版本的项目。我已经能够轻松地转换其中的大部分内容,但是底部的链接/导航给我带来了一些问题。 转换此/处理
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improv
我一直在我的 emacs c/c++ 开发设置中试验 cedet 和语义,除了一个小细节外,我对它非常满意。 我使用 ede-cpp-root-project 创建一个项目,并给出我的项目的根目录以及
引用问题自http://www.garfieldtech.com/blog/put-up-with-put (这是针对 Drupal 开源项目的,有点元,因为这里没有代码): GET、HEAD 和 P
我有以下代码。 let v_blue = UIView() v_blue.backgroundColor = UIColor.blueColor() l
我目前正在 objc.io 上阅读优秀的 Advanced Swift 书籍,但遇到了一些我不明白的问题。 如果您在操场上运行以下代码,您会注意到在修改字典中包含的结构时,下标访问会生成一个副本,但随
谁能给我一个关于 Flutter 上下文中语义概念的清晰解释(或链接)(它实际上是什么,何时使用,更新...)? 我在谷歌上搜索了很多,但到目前为止还没有找到任何好的解释。 非常感谢, 最佳答案 Di
这是我的代码 Was this what you wanted? It's good to see you again.
我有一个侧边栏,其中包含应用程序的主导航。它还包含一个 button 触发侧边栏的打开/关闭。在语义方面,标记应该是什么样的? 我应该把侧边栏放在一边,然后只在周围设置导航吗主导航,不包括打开/关闭触
考虑下面这行 Lisp 代码: (some-function 7 8 | 9) ;; some comment. note the extra indentation 该点位于“8”和
我是一名优秀的程序员,十分优秀!