- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这三种填充 vector 的方式之间是否存在性能差异?
#include <vector>
#include <numeric>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<int> v(10);
std::iota(v.begin(), v.end(), 0);
std::vector<int> v2(10);
int i = 0;
std::generate(v2.begin(), v2.end(), [&i](){return i++; });
std::vector<int> v3(10);
i = 0;
for (auto& j : v3)
{
j = i++;
}
return 0;
}
我知道它们都产生相同的结果,我只想知道较大的 vector 是否存在速度差异。 不同类型的答案会有所不同吗?
最佳答案
我们可以查看输出程序集(我使用了 gcc.godbolt.org,gcc -03,以及您的代码):
1) 第一个版本,带有 std::iota
:
main:
sub rsp, 8
mov edi, 40
call operator new(unsigned long)
mov DWORD PTR [rax], 0
mov DWORD PTR [rax+4], 1
mov rdi, rax
mov DWORD PTR [rax+8], 2
mov DWORD PTR [rax+12], 3
mov DWORD PTR [rax+16], 4
mov DWORD PTR [rax+20], 5
mov DWORD PTR [rax+24], 6
mov DWORD PTR [rax+28], 7
mov DWORD PTR [rax+32], 8
mov DWORD PTR [rax+36], 9
call operator delete(void*)
xor eax, eax
add rsp, 8
ret
2) 带有 std::generate
和 Lambda 的版本:
main:
sub rsp, 8
mov edi, 40
call operator new(unsigned long)
mov DWORD PTR [rax], 0
mov DWORD PTR [rax+4], 1
mov rdi, rax
mov DWORD PTR [rax+8], 2
mov DWORD PTR [rax+12], 3
mov DWORD PTR [rax+16], 4
mov DWORD PTR [rax+20], 5
mov DWORD PTR [rax+24], 6
mov DWORD PTR [rax+28], 7
mov DWORD PTR [rax+32], 8
mov DWORD PTR [rax+36], 9
call operator delete(void*)
xor eax, eax
add rsp, 8
ret
3) 最后一个版本,手写循环:
main:
sub rsp, 8
mov edi, 40
call operator new(unsigned long)
mov DWORD PTR [rax], 0
mov DWORD PTR [rax+4], 1
mov rdi, rax
mov DWORD PTR [rax+8], 2
mov DWORD PTR [rax+12], 3
mov DWORD PTR [rax+16], 4
mov DWORD PTR [rax+20], 5
mov DWORD PTR [rax+24], 6
mov DWORD PTR [rax+28], 7
mov DWORD PTR [rax+32], 8
mov DWORD PTR [rax+36], 9
call operator delete(void*)
xor eax, eax
add rsp, 8
ret
结论:
正如预期的那样,所有这三个都生成了相同的程序集(全部展开),使用了一个不错的编译器,启用了优化。
所以不,没有性能差异。
注意:
我做了比较程序集的测试, vector 大到没有展开的循环(我不知道 GCC 启发式方法,但它开始时大小 >~ 15)。
在那种情况下,对于所有 3 种情况,程序集仍然相同,我不会在此处复制输出,因为它不会带来太多答案,但问题是编译器是真的非常擅长优化这种代码。
关于c++ - iota、generate 和手动循环是否都执行相同的操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25475677/
我假设“i”是递增的,而“a”是分配的,但我无法弄清楚或找到答案。此外,它看起来与我认为令人困惑的非标准 itoa 非常相似。 最佳答案 C++ iota 不是首字母缩写词或首字母缩写词。就是“iot
在下面的代码中: const ( signature uint32 = 0xae3179fb dhkxGroup = 2 ReplySuccessful byte = iota
这三种填充 vector 的方式之间是否存在性能差异? #include #include #include #include int main() { std::vector v(1
iota 模板函数已添加到标准库中,以用递增的值序列填充迭代器范围。 template void iota(ForwardIterator first, ForwardIterat
iota函数以前在 中 header 。已改为 . 我需要保留旧方法以实现向后兼容性,因此我想使用预处理器选项来选择要包含的正确 header 。 这什么时候改变了,我应该使用哪个预处理器选项?
以下示例使用 iota 定义了一系列从 3333 开始的端口号。 package main import ( "fmt" ) const ( FirstPort = iota+3333 Sec
来自 Python 世界,我找到了函数 std::iota非常有限。为什么接口(interface)被限制为不带任何 UnaryFunction ? 例如我可以转换 >>> x = range(0,
作为标题,golang中iota的全称是什么(不是用法): const ( // iota is reset to 0 c0 = iota // c0 == 0 c1 = iota
Iota 是一种非常小的“编程语言”,只使用一个组合器。我有兴趣了解它的工作原理,但是以我熟悉的语言查看实现会很有帮助。 我找到了一个用 Scheme 编写的 Iota 编程语言的实现。不过,我在将其
ranges-v3库中的closed_iota和iota有什么区别? 最佳答案 第二种遵循标准的C++表达范围的方法-默认为右侧打开范围。第一个是包容性的。iota接受两个参数:start和end。它
由于没有基于索引的parallel for algorithm在 c++17 , 我想知道 ranges::view::iota可以与std::for_each结合使用模仿那个。即: using na
再次提出这个问题,我深表歉意。我之前就 Haskell 实现问过这个问题 here ,但我仍然难以理解这是如何工作的。此外,我发现极简编程语言的概念绝对令人着迷并且无法摆脱它......无论如何,这不
我最近一直在利用 iota递增 int 类型 vector 的语句.但现在我正在尝试使用该语句来递增具有 2 个成员的显式类。 下面是整数 vector 的用法: vector n(6); iota
为了了解 C++11 的复杂性,我正在研究 unique_ptr有一点。 我想知道,有什么办法可以使用iota吗?初始化 unique_ptr 的容器? 我从 unique-ptr-less 解决方案
我试图编译这段代码:- #include using namespace std; int main() { vector v(5); iota(v.begin(), v.end()
以下程序打印出一副洗好的纸牌(作为整数): #include #include #include #include typedef unsigned int card; typedef std
请原谅我对 Go 的了解非常有限。我有这样的定义 type ErrorVal int const ( LEV_ERROR ErrorVal = iota LEV_WARNING
我有这个 Go 代码: package main import "fmt" type baseGroup int const ( fooGroup baseGroup = iota + 1
假设我们有一个 map[int]string我们想这样定义它: var a map[int]string = { 1: "some" 3: "value" 4: "maintained" 7
假设我有下一个 c 程序: #include int main(int args, char* argv[]) { enum RC { APPLE=0, OR
我是一名优秀的程序员,十分优秀!