首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >相对于memset,我可以期望std::fill_n(ptr,n,0)的性能吗?

相对于memset,我可以期望std::fill_n(ptr,n,0)的性能吗?
EN

Stack Overflow用户
提问于 2016-12-21 17:55:36
回答 2查看 2K关注 0票数 8

对于作为指针的迭代器ptrstd::fill_n(ptr, n, 0)应该执行与memset(ptr, 0, n * sizeof(*ptr))相同的操作(但请参阅@KeithThompson对this answer的评论)。

对于C++11/ C++ 14/C++17模式下的C++编译器,在什么条件下可以将它们编译成相同的代码?当/如果它们没有编译到相同的代码时,-O0?-O3的性能会有显著的差异吗?

注:当然,的某些/大部分答案可能是编译器特有的。我只对一个或两个特定的编译器感兴趣,但是请写一下你知道答案的编译器。

EN

回答 2

Stack Overflow用户

发布于 2016-12-21 18:38:07

答案取决于标准库的实现。

例如,MSVC基于您要填充的内容的类型,有几个std::fill_n实现。

char*signed char*unsigned char*调用memset,它将直接调用memset来填充数组。

代码语言:javascript
运行
复制
inline char *_Fill_n(char *_Dest, size_t _Count, char _Val)
{   // copy char _Val _Count times through [_Dest, ...)
_CSTD memset(_Dest, _Val, _Count);
return (_Dest + _Count);
}

如果您用另一种类型调用,它将填充一个循环:

代码语言:javascript
运行
复制
template<class _OutIt,
class _Diff,
class _Ty> inline
_OutIt _Fill_n(_OutIt _Dest, _Diff _Count, const _Ty& _Val)
{   // copy _Val _Count times through [_Dest, ...)
for (; 0 < _Count; --_Count, (void)++_Dest)
    *_Dest = _Val;
return (_Dest);
}

确定特定编译器和标准库实现上的开销的最佳方法是使用这两个调用来分析代码。

票数 6
EN

Stack Overflow用户

发布于 2016-12-22 07:44:23

对于所有适合memset的场景(即,您的所有对象都是PODs),您很可能会发现,在启用任何级别的优化时,这两个语句是等价的。

对于memset不合适的情况,比较是没有意义的,因为使用memset会导致程序错误。

您可以很容易地使用戈德波特(以及其他许多工具)来检查自己:

例如,在gcc6.2上,这两个函数生成与优化级别-O3完全相同的代码:

代码语言:javascript
运行
复制
#include <algorithm>
#include <cstring>

__attribute__((noinline))
  void test1(int (&x) [100])
{
  std::fill_n(&x[0], 100, 0);
}

__attribute__((noinline))
  void test2(int (&x) [100])
{
  std::memset(&x[0], 0, 100 * sizeof(int));
}

int main()
{
  int x[100];
  test1(x);
  test2(x);
}

https://godbolt.org/g/JIwI5l

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41268994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档