[c++]乱用移动语义的例子

90 阅读2分钟

最近在学习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++]深入理解移动语义

通过以上学习,我们知道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操作之后,并没有被”销毁“。

综上所诉,作者采用移动语义来操作,除了炫技之后没有任何好处。