对于作为指针的迭代器ptr
,std::fill_n(ptr, n, 0)
应该执行与memset(ptr, 0, n * sizeof(*ptr))
相同的操作(但请参阅@KeithThompson对this answer的评论)。
对于C++11/ C++ 14/C++17模式下的C++编译器,在什么条件下可以将它们编译成相同的代码?当/如果它们没有编译到相同的代码时,-O0?-O3的性能会有显著的差异吗?
注:当然,的某些/大部分答案可能是编译器特有的。我只对一个或两个特定的编译器感兴趣,但是请写一下你知道答案的编译器。
发布于 2016-12-21 18:38:07
答案取决于标准库的实现。
例如,MSVC基于您要填充的内容的类型,有几个std::fill_n
实现。
用char*
、signed char*
或unsigned char*
调用memset
,它将直接调用memset
来填充数组。
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);
}
如果您用另一种类型调用,它将填充一个循环:
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);
}
确定特定编译器和标准库实现上的开销的最佳方法是使用这两个调用来分析代码。
发布于 2016-12-22 07:44:23
对于所有适合memset
的场景(即,您的所有对象都是PODs),您很可能会发现,在启用任何级别的优化时,这两个语句是等价的。
对于memset
不合适的情况,比较是没有意义的,因为使用memset
会导致程序错误。
您可以很容易地使用戈德波特(以及其他许多工具)来检查自己:
例如,在gcc6.2上,这两个函数生成与优化级别-O3完全相同的代码:
#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://stackoverflow.com/questions/41268994
复制相似问题