考虑以下c ++源代码:
int _end[1050];
int main() {
for (int i = 0; i < 1050; i++)
_end[i] = 0;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译线: g++ main.cpp -o main -O0
在Ubuntu 14.04下使用gcc-4.8.4和clang-3.6.0时,运行此代码会导致分段错误.奇怪的行为是符号_end指向静态分配的数组的末尾_end,而不是它的开头.如果我们替换_end用end_,一切工作正常.
此外,如果我们要求gcc通过提供-S命令行参数输出汇编代码,则带有"_end"的版本与具有任何其他数组名称的版本之间没有显着差异:
$ g++ main.cpp -o main.s -O0 -S
$ g++ main2.cpp -o main2.s -O0 -S
$ diff main.s main2.s
1,2c1,2
< .file "main.cpp"
< .globl _end
---
> .file "main2.cpp"
> .globl end_
5,7c5,7
< .type _end, @object
< .size _end, 4200 …Run Code Online (Sandbox Code Playgroud) TL; DR我想写一个模板函数Process(T value),根据非成员函数的存在,它对不同的值表现不同CreateProcessor<T>().我能做些什么?
我有SFINAE的问题.假设我们需要支持CreateProcessor返回IProcessor<T>某种类型类型的接口实现的函数T.
在C++中,我们不能创建仅在返回类型上有所不同的函数的多个重载,因此我们必须使函数CreateProcessor也是由参数化的模板函数T.
现在假设我们要编写一个模板函数Process<T>(T value),它根据存在的不同而工作CreateProcessor<T>(),即它应该value在CreateProcessor<T>()实现的情况下使用处理器进行处理,否则会导致错误.
我试图编写以下代码:
#include <cstdio>
#include <type_traits>
// A workaround for void_t as described here: http://en.cppreference.com/w/cpp/types/void_t.
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
// An interface for a processor that receives a value of specific type.
template<class T>
class IProcessor {
public:
virtual void …Run Code Online (Sandbox Code Playgroud) 假设我们想要将n数据字节从void* src复制到void* dst。众所周知,标准库的实现经过memcpy严格优化,可以使用依赖于平台的向量化指令和各种其他技巧来尽可能快地执行复制。
现在假设p后面的数据字节src + n是可读的并且p后面的数据字节dst + n是可写的。另外,假设在 中写入任意垃圾也是可以的[dst + n, dst + n + p)。
显然,这些假设扩大了我们可能采取的行动的范围,可能导致更快的 memcpy。例如,我们可以在少量未对齐的 128 位指令(加载 + 存储)中复制少于 16 个尾随字节的某些部分。也许这种额外的假设还允许使用其他技巧。
01234 ..... n
src: abcdabcdabcdabcdabcdabcGARBAGEGA
v v
dst: ______(actl dst)________(wrtbl)_
| block1 || block2 |
Run Code Online (Sandbox Code Playgroud)
请注意,当您需要在分配的容量足以容纳p+ 总字符串大小字节的缓冲区内附加字符串序列时,这些假设实际上相当实用。例如,以下例程可能发生在数据库内部的某个位置:
给你一个二进制字符串
char* dictionary和一个整数数组int* offsets,它是字典中偏移量的单调序列;这两个变量表示从磁盘获取的字符串字典。您还有一个整数数组,int* indices指示必须将字典字符串写入输出缓冲区的顺序char* buffer。
使用上述技术,您可以安全地编写每个新字符串,而不关心其右侧的垃圾,因为它将被要附加的下一个字符串覆盖。
问题是: