最近在学习Linux网络编程的过程中看到这样一段代码,百思不得其解,我不明白作者为什么要这么做
代码如下:
using TcpConnectionCallback = std::function<void(const TcpConnectionPtr&)>;
void setAllCallbacks(TcpConnectionCallback && onConnection,
TcpConnectionCallback && onMessage,
TcpConnectionCallback && onClose)
{
_loop.setConnectionCallback(std::move(onConnection));
_loop.setMessageCallback(std::move(onMessage));
_loop.setCloseCallback(std::move(onClose));
}
void EventLoop::setConnectionCallback(TcpConnectionCallback && cb)
{
_onConnectionCb = std::move(cb);
}
void EventLoop::setMessageCallback(TcpConnectionCallback && cb)
{
_onMessageCb = std::move(cb);
}
void EventLoop::setCloseCallback(TcpConnectionCallback && cb)
{
_onCloseCb = std::move(cb);
}
如代码所示,setAllCallbacks接受三个函数指针,即三个分别用于处理TCP连接抵达、TCP消息抵达、TCP断开连接的三个函数。我很好奇这里作者为什么要使用右值引用和移动语义。我对这一块不是很熟。所以特意学习了这方面的知识。
通过以上学习,我们知道c++移动语义是用于避免程序中不必要的拷贝操作(临时对象、右值),对于资源密集型操作,可以极大的节省时间和空间。
而原本的代码中采用移动语义的对象仅仅只是一个函数指针,对于函数指针,一般情况下并不需要采用移动语义。因为函数指针本身的大小通常非常小,直接拷贝或传递引用即可。
此外,和上述文章中描述的基本数据类型一样,对指针采用移动语义本身不会有任何效果。
见以下代码:
void onMessage() {
cout << " on message !" << endl;
}
void onConnection() {
cout << " has connected!" << endl;
}
void onClose(){
cout << " has closed!" << endl;
}
int main() {
void (*func1)() = onMessage;
void (*func2)() = onConnection;
void (*func3)() = onClose;
auto func1_copy = std::move(func1);
auto func2_copy = std::move(func2);
auto func3_copy = std::move(func3);
func1();
func2();
func3();
func1_copy();
func2_copy();
func3_copy();
}
输出如下:
on message !
has connected!
has closed!
on message !
has connected!
has closed!
原本的三个函数指针func1/func2/func3在std::move操作之后,并没有被”销毁“。
综上所诉,作者采用移动语义来操作,除了炫技之后没有任何好处。