move与函数指针的简单使用

这篇具有很好参考价值的文章主要介绍了move与函数指针的简单使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

std::move()

C++11的标准库 提供了一个非常有用的函数 std::move(),std::move() 函数将一个左值强制转化为右值引用,以用于移动语义。

就是说 std::move(str); 之后原来的值因为变成了右值失效了
但是这样赋值可以避免出现拷贝

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main()
{
    string str = "hello";
    cout << "before str: " << str << endl;

    vector<string> vstr;
    vstr.emplace_back(std::move(str));
    cout << "after  str: " << str << endl;

    return 0;
}

str 就没有了因为被转移语义了


#include <iostream>
#include <functional>
#include <utility>
#include "tinyNetWorkLib.h"
class People{
  using actionEvent = std::function<void()>;

public:
  People():value(2){}
  People(int v):value(v){}
  void setCryEvent(actionEvent func){ cry = std::move(func); }
  void setSimleEvent(actionEvent func){ smile = std::move(func);}
  void handleEvent(Timestamp receiverTime){
      if(value >= 0){
        smile(); 
          cout<<receiverTime.toFormattedString()<<endl;
      }else{
          cry();
          cout<<receiverTime.toFormattedString()<<endl;
      }
  }
private:
  actionEvent cry;
  actionEvent smile;
  int value;
};
int main()
{
    std::function<void()> func = []{
        std:: cout<<"happy"<<std::endl;       
    };
    std::function<void()> func2 = []{
        std::cout<<"cry"<<std::endl;
    };
    People peo;
    peo.setCryEvent(func2);
    peo.setSimleEvent(func);
    peo.handleEvent(Timestamp ::now());
   // std::cout << "Hello world" << std::endl;
   
    return 0;
}


执行结果

happy
2023/08/27 20:49:59

这里函数指针还能用,因为这里转移语义的对象是参数

给出依赖文件的代码Timestamp 复制下来用就好

记得给个#ifndef这里自己

#include <functional>
#include <set>
#include <sys/time.h>
#include <sys/eventfd.h>
#include <fcntl.h>
#include <unistd.h>
#include  <mutex>
#include<unordered_map>
using namespace std;
class Timestamp
{
public:
    Timestamp()
        : microSecondsSinceEpoch_(0)
    {
    }

    explicit Timestamp(int64_t microSecondsSinceEpoch)
        : microSecondsSinceEpoch_(microSecondsSinceEpoch)
    {
    }

    // 获取当前时间戳
    static Timestamp now();

    //用std::string形式返回,格式[millisec].[microsec]
    std::string toString() const;
    //格式, "%4d年%02d月%02d日 星期%d %02d:%02d:%02d.%06d",时分秒.微秒
    std::string toFormattedString(bool showMicroseconds = false) const;

    //返回当前时间戳的微妙
    int64_t microSecondsSinceEpoch() const { return microSecondsSinceEpoch_; }
    //返回当前时间戳的秒数
    time_t secondsSinceEpoch() const
    { 
        return static_cast<time_t>(microSecondsSinceEpoch_ / kMicroSecondsPerSecond); 
    }

    // 失效的时间戳,返回一个值为0的Timestamp
    static Timestamp invalid()
    {
        return Timestamp();
    }

    // 1秒=1000*1000微妙
    static const int kMicroSecondsPerSecond = 1000 * 1000;

private:
    // 表示时间戳的微秒数(自epoch开始经历的微妙数)
    int64_t microSecondsSinceEpoch_;
};

/**
 * 定时器需要比较时间戳,因此需要重载运算符
 */
inline bool operator<(Timestamp lhs, Timestamp rhs)
{
    return lhs.microSecondsSinceEpoch() < rhs.microSecondsSinceEpoch();
}

inline bool operator==(Timestamp lhs, Timestamp rhs)
{
    return lhs.microSecondsSinceEpoch() == rhs.microSecondsSinceEpoch();
}

// 如果是重复定时任务就会对此时间戳进行增加。
inline Timestamp addTime(Timestamp timestamp, double seconds)
{
    // 将延时的秒数转换为微妙
    int64_t delta = static_cast<int64_t>(seconds * Timestamp::kMicroSecondsPerSecond);
    // 返回新增时后的时间戳
    return Timestamp(timestamp.microSecondsSinceEpoch() + delta);
}

Timestamp Timestamp::now()
{
    struct timeval tv;
    // 获取微妙和秒
    // 在x86-64平台gettimeofday()已不是系统调用,不会陷入内核, 多次调用不会有性能损失.
    gettimeofday(&tv, NULL);
    int64_t seconds = tv.tv_sec;
    // 转换为微妙
    return Timestamp(seconds * kMicroSecondsPerSecond + tv.tv_usec);
}

// 2022/08/26 16:29:10
// 20220826 16:29:10.773804
std::string Timestamp::toFormattedString(bool showMicroseconds) const
{
    char buf[64] = {0};
    time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / kMicroSecondsPerSecond);
    // 使用localtime函数将秒数格式化成日历时间
    tm *tm_time = localtime(&seconds);
    if (showMicroseconds)
    {
        int microseconds = static_cast<int>(microSecondsSinceEpoch_ % kMicroSecondsPerSecond);
        snprintf(buf, sizeof(buf), "%4d/%02d/%02d %02d:%02d:%02d.%06d",
                tm_time->tm_year + 1900,
                tm_time->tm_mon + 1,
                tm_time->tm_mday,
                tm_time->tm_hour,
                tm_time->tm_min,
                tm_time->tm_sec,
                microseconds);
    }
    else
    {
        snprintf(buf, sizeof(buf), "%4d/%02d/%02d %02d:%02d:%02d",
                tm_time->tm_year + 1900,
                tm_time->tm_mon + 1,
                tm_time->tm_mday,
                tm_time->tm_hour,
                tm_time->tm_min,
                tm_time->tm_sec);
    }
    return buf;
}



最后我们给出要给第一个版本的channel

一个文件描述符,发生读事件 写时间 关闭事件 错误事
文件描述符就是一个整形变量
int revents 表示这个文件描述符的心情(状态)
通过位运算表示 和EPOLLINT OUT HUB 先不管

#include <functional>
#include "tinyNetWorkLib.h"
#include <sys/epoll.h>

class Channel{
   using EventCallback = std::function<void()>;
   using ReadEventCallback = std::function<void(Timestamp)>;
public:    
    Channel(int fd):fd_(fd){};

    void setReadCallback(ReadEventCallback cb) { readCallback_ = std::move(cb); }
    void setWriteCallback(EventCallback cb) { writeCallback_ = std::move(cb); }
    void setCloseCallback(EventCallback cb) { closeCallback_ = std::move(cb); }
    void setErrorCallback(EventCallback cb) { errorCallback_ = std::move(cb); } 
    void set_revents(int revt){ revents = revt; }
    void handleWithGuard(Timestamp receiverTime){
        if(revents & EPOLLHUP && !(revents & EPOLLIN)){
            if(closeCallback_){
                 closeCallback_();
            }
        }
        if(revents & EPOLLERR){
            if(errorCallback_){
                errorCallback_();
            }    
        }
        
        if(revents & (EPOLLIN|EPOLLPRI)){
            if(readCallback_){
                 readCallback_(receiverTime);
            }
        }
        if(revents & EPOLLOUT){
            if(writeCallback_){
                 writeCallback_();
            }
        }
    }

private:
   
   ReadEventCallback readCallback_;
   EventCallback writeCallback_;
   EventCallback closeCallback_;
   EventCallback errorCallback_;
   const int fd_;
   int revents;

};

这个和我们People类设计几乎一样除了设计了一点系统知识文章来源地址https://www.toymoban.com/news/detail-677446.html

#include <iostream>
#include <functional>
#include <utility>
#include "tinyNetWorkLib.h"
#include "Channel.h"
class People{
  using actionEvent = std::function<void()>;

public:
  People():value(2){}
  People(int v):value(v){}
  void setCryEvent(actionEvent func){ cry = std::move(func); }
  void setSimleEvent(actionEvent func){ smile = std::move(func);}
  void handleEvent(Timestamp receiverTime){
      if(value >= 0){
        smile(); 
          cout<<receiverTime.toFormattedString()<<endl;
      }else{
          cry();
          cout<<receiverTime.toFormattedString()<<endl;
      }
  }
  int set_value(int v){value = v;}
private:
  actionEvent cry;
  actionEvent smile;
  int value;
};
int main()
{
    std::function<void()> func = []{
        std:: cout<<"happy"<<std::endl;       
    };
    std::function<void()> func2 = []{
        std::cout<<"cry"<<std::endl;
    };
   // People peo;
   // peo.setCryEvent(func2);
   // peo.setSimleEvent(func);
  //  peo.handleEvent(Timestamp ::now());
   // std::cout << "Hello world" << std::endl;
  // func();

   Channel chanel(1);
   chanel.set_revents(EPOLLOUT);

   chanel.setWriteCallback(func);
   chanel.handleWithGuard(Timestamp::now());
    return 0;
}

执行结果
happy

到了这里,关于move与函数指针的简单使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 网络编程套接字(2): 简单的UDP网络程序

    3.1 服务端创建 (1) 创建套接字 create an endpoint for communication: 创建用于通信的端点 关于socket参数详细介绍: (1) domain: 指定套接字的通信域,相当于 struct sockaddr结构体的前16比特位(2字节) domain的选项是以宏的形式给出的,我们直接选用即可。常用就是上面框住的两个: AF_UNIX,本

    2024年02月10日
    浏览(56)
  • 网络编程套接字(2)——简单的TCP网络程序

    我们将TCP服务器封装成一个类,当我们定义出一个服务器对象后需要马上对服务器进行初始化,而初始化TCP服务器要做的第一件事就是创建套接字。 TCP服务器在调用socket函数创建套接字时,参数设置如下: 协议家族选择 AF_INET ,因为我们要进行的是网络通信。 创建套接字时

    2024年02月06日
    浏览(62)
  • Socket编程接口API并实现简单的TCP网络编程

    #include sys/types.h #include sys/socket.h socket()创建套接字,成功返回套接字的文件描述符,失败返回-1 domain: 设置套接字的协议簇, AF_UNIX AF_INET AF_INET6 type: 设置套接字的服务类型 SOCK_STREAM SOCK_DGRAM protocol: 一般设置为 0,表示使用默认协议 int socket(int domain, int type, int protocol); bind()将

    2024年02月13日
    浏览(42)
  • 【网络编程】UDP简单实现翻译软件与网络聊天室

    在上一章【网络编程】demo版UDP网络服务器实现实现了客户端和服务端之间的数据的发送与接收,上一章我们是直接让服务端把接收到的数据打印出来。 但是服务端并不是只接收到数据就完了,它还要 处理任务 。 所以我们可以在服务端设置一个回调函数: 用来处理接收到的

    2024年02月05日
    浏览(80)
  • 基于Python编程实现简单网络爬虫实现

    引言 网络爬虫(英语:web crawler),也叫网络蜘蛛(spider),是一种用来自动浏览万维网的网络机器人。其目的一般为编纂网络索引。 --维基百科 网络爬虫可以将自己所访问的页面保存下来,以便搜索引擎事后生成索引供用户搜索。 一般有两个步骤:1.获取网页内容  2.对获

    2024年01月18日
    浏览(41)
  • 【Linux网络】网络编程套接字 -- 基于socket实现一个简单UDP网络程序

    我们把数据从A主机发送到B主机,是目的吗?不是,真正通信的不是这两个机器!其实是这两台机器上面的软件(人) 数据有 IP(公网) 标识一台唯一的主机 ,用谁来标识各自主机上客户或者服务进程的唯一性呢? 为了更好的表示一台主机上服务进程的唯一性,我们采用 端口号

    2024年02月12日
    浏览(159)
  • Linux网络编程---IP 地址格式转换函数

      我们更容易阅读的IP地址是以点分十进制表示的,例如:192.168.5.10 ,这是一种字符串的形式,但是计算器所需要的IP地址是以二进制进行表示,这便需要我们在点分十进制字符串和二进制地址之间进行转换。   点分十进制字符串和二进制地址之间的转换函数主要有:

    2024年01月18日
    浏览(49)
  • 【计算机网络】网络编程套接字&UDP服务器客户端的简单模拟

    需要云服务器等云产品来学习Linux的同学可以移步/–腾讯云–/官网,轻量型云服务器低至112元/年,优惠多多。(联系我有折扣哦) 每台主机都有自己的IP地址,当数据在进行通信的时候,除了要发送的数据外,在报头里面还要包含发送方的IP和接收方的IP,这里发送方的IP就

    2024年02月20日
    浏览(64)
  • 【探索Linux】P.28(网络编程套接字 —— 简单的UDP网络程序模拟实现)

    在前一篇文章中,我们详细介绍了UDP协议和TCP协议的特点以及它们之间的异同点。 本文将延续上文内容,重点讨论简单的UDP网络程序模拟实现 。通过本文的学习,读者将能够深入了解UDP协议的实际应用,并掌握如何编写简单的UDP网络程序。让我们一起深入探讨UDP网络程序的

    2024年04月08日
    浏览(174)
  • 【探索Linux】P.29(网络编程套接字 —— 简单的TCP网络程序模拟实现)

    在前一篇文章中,我们详细介绍了UDP协议和TCP协议的特点以及它们之间的异同点。 本文将延续上文内容,重点讨论简单的TCP网络程序模拟实现 。通过本文的学习,读者将能够深入了解TCP协议的实际应用,并掌握如何编写简单的TCP网络程序。让我们一起深入探讨TCP网络程序的

    2024年04月14日
    浏览(87)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包