我一直在玩x86-64程序集试图了解更多有关可用的各种SIMD扩展(MMX,SSE,AVX).
为了了解GCC如何将不同的C或C++构造转换为机器代码,我一直在使用Compiler Explorer,这是一个极好的工具.
在我的一个"游戏会话"期间,我想看看GCC如何优化整数数组的简单运行时初始化.在这种情况下,我试图将数字0到2047写入2048个无符号整数的数组.
代码如下:
unsigned int buffer[2048];
void setup()
{
for (unsigned int i = 0; i < 2048; ++i)
{
buffer[i] = i;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我启用优化和AVX-512指令,-O3 -mavx512f -mtune=intelGCC 6.3会生成一些非常聪明的代码:)
setup():
mov eax, OFFSET FLAT:buffer
mov edx, OFFSET FLAT:buffer+8192
vmovdqa64 zmm0, ZMMWORD PTR .LC0[rip]
vmovdqa64 zmm1, ZMMWORD PTR .LC1[rip]
.L2:
vmovdqa64 ZMMWORD PTR [rax], zmm0
add rax, 64
cmp rdx, rax
vpaddd zmm0, zmm0, zmm1
jne .L2
ret
buffer:
.zero 8192
.LC0:
.long 0
.long …Run Code Online (Sandbox Code Playgroud) 我最近一直在研究C++中的转发引用,下面简要概述了我目前对该概念的理解.
假设我有一个模板函数,foo它将转发引用转换为类型的单个参数T.
template<typename T>
void foo(T&& arg);
Run Code Online (Sandbox Code Playgroud)
如果我用左值调用此函数,那么T将推断为由于参考折叠规则T&使arg参数成为类型.T&T& && -> T&
如果使用未命名的临时函数(例如函数调用的结果)调用此函数,T则将推断为T使arg参数为类型T&&.
foo但是,里面arg是一个命名参数,所以std::forward如果我想将参数传递给其他函数并仍然保持其值类别,我将需要使用.
template<typename T>
void foo(T&& arg)
{
bar(std::forward<T>(arg));
}
Run Code Online (Sandbox Code Playgroud)
据我所知,cv-qualifiers不受此转发的影响.这意味着如果我使用命名的const变量调用foo,那么T将推断为const T&,因此类型arg也将const T&归因于引用折叠规则.对于const rvalues T将被推导为const T,因此arg将是类型const T&&.
这也意味着如果我修改arg内部的值,foo如果我将一个const变量传递给它,我将得到编译时错误.
现在我的问题.假设我正在编写容器类,并希望提供一种将对象插入容器的方法.
template<typename T>
class Container
{
public: …Run Code Online (Sandbox Code Playgroud) 我和一位同事正试图实现一个简单的多态类层次结构.我们正在研究嵌入式系统,仅限于使用C编译器.我们有一个基本的设计思想,在没有警告的情况下编译(-Wall -Wextra -fstrict-aliasing -pedantic),并且在gcc 4.8.1下运行正常.
但是,我们有点担心别名问题,因为我们还不完全理解这会成为问题.
为了演示我们已经编写了一个带有"接口"IHello的玩具示例和两个实现此接口'Cat'和'Dog的类.
#include <stdio.h>
/* -------- IHello -------- */
struct IHello_;
typedef struct IHello_
{
void (*SayHello)(const struct IHello_* self, const char* greeting);
} IHello;
/* Helper function */
void SayHello(const IHello* self, const char* greeting)
{
self->SayHello(self, greeting);
}
/* -------- Cat -------- */
typedef struct Cat_
{
IHello hello;
const char* name;
int age;
} Cat;
void Cat_SayHello(const IHello* self, const char* greeting)
{
const Cat* cat = (const Cat*) self;
printf("%s I …Run Code Online (Sandbox Code Playgroud) 我目前正在编写一个非常简单的Web服务器,以了解有关底层套接字编程的更多信息。更具体地说,我使用C ++作为主要语言,并且尝试使用更高级的API将低级C系统调用封装在C ++类中。
我编写了一个Socket类,该类管理套接字文件描述符并使用RAII处理打开和关闭。此类还公开了面向连接的套接字(TCP)的标准套接字操作,例如绑定,监听,接受,连接等。
在阅读了send和recv系统调用的手册页之后,我意识到我需要在某种形式的循环内调用这些函数,以确保所有字节都可以成功发送/接收。
我发送和接收的API与此类似
void SendBytes(const std::vector<std::uint8_t>& bytes) const;
void SendStr(const std::string& str) const;
std::vector<std::uint8_t> ReceiveBytes() const;
std::string ReceiveStr() const;
Run Code Online (Sandbox Code Playgroud)
对于发送功能,我决定send在这样的循环内使用阻塞调用(这是一个内部辅助函数,可同时用于std :: string和std :: vector)。
template<typename T>
void Send(const int fd, const T& bytes)
{
using ValueType = typename T::value_type;
using SizeType = typename T::size_type;
const ValueType *const data{bytes.data()};
SizeType bytesToSend{bytes.size()};
SizeType bytesSent{0};
while (bytesToSend > 0)
{
const ValueType *const buf{data + bytesSent};
const ssize_t retVal{send(fd, buf, bytesToSend, 0)}; …Run Code Online (Sandbox Code Playgroud)