C++ 引用踩的坑

Posted 落霞与孤鹜亓飞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 引用踩的坑相关的知识,希望对你有一定的参考价值。

我在ns3模拟器网络的基础上想实现一个简单的区块链系统,在这个区块链系统中,每两个邻居节点之间都会记录互相广播的交易哈希。
于是每个节点都有两个 map 存储,其结构为:
std::map<IPV4Address, std::vector<std::string>> m_sendTxHash;
std::map<IPV4Address, std::vector<std::string>> m_recvTxHash;
这两个 map 的键是节点的 IP 地址,值是向该 IP 发送过的或者从该 IP 接收到的交易哈希。

在我的实现中,一个节点在转发区块时,需要获取向邻居节点发送过的以及从该节点接收过的所有交易哈希值。例如其中某个邻居节点的 IP 地址为 peerIP,通过如下方式获取发送的和接受的交易哈希:
m_sendTxHash[peerIP]m_recvTxHash[peerIP]
但是这样会使得整个变量长度很长,书写起来十分不便,于是我想到了使用引用,不会造成额外的内存拷贝,同时可以让变量名更短更容易书写。
于是我写下了下面的代码:

class IPV4Address;
std::map<IPV4Address, std::vector<std::string>> m_sendTxHash;
std::map<IPV4Address, std::vector<std::string>> m_recvTxHash;

std::vector<std::string> tmp;
std::vector<std::string>& sendTxHash = tmp;
std::vector<std::string>& recvTxHash = tmp;
IPV4Address peerIP("127.0.0.1");
if(m_sendTxHash.count(peerIP))
	sendTxHash = m_sendTxHash[peerIP];
if(m_recvTxHash.count(peerIP))
	recvTxHash = m_recvTxHash[peerIP];

为什么刚开始要让 recvTxHash 和 sendTxHash 作为 tmp 的别名呢?因为 m_sendTxHash 和 m_recvTxHash 中可能不包含我们的 peerIP,因此为了谨慎期间,我先让 recvTxHash 和 sendTxHash 指向一个空的 tmp, 如果 m_sendTxHash 和 m_recvTxHash 中存在 peerIP 的记录,我们就可以再修改 recvTxHash 和 sendTxHash 的指向。

然而实际上,即使成功进入代码中的 if 判断语句并且执行,也只是对 tmp 变量进行了修改,而最终 sendTxHash 和 recvTxHash 实际上指向了同一个变量 tmp,他们并没有记录我想象中的 m_sendTxHash[peerIP]m_recvTxHash[peerIP]

源于我对引用的理解不到位,导致我查找这段代码引起的 bug 整整找了三天。

另外一个bug

写代码的时候,需要给函数F传输两个队列A和B,队列A和队列B中的数据来自socket的数据流中。
然而将数据流从数据流中读取到队列A和队列B的过程中,把本应该读取到队列B的数据读取到了一个临时的变量C中,传输参数的时候还是传输了A和B,结果死活不对,后来经过长时间的debug,发现数据流根本没有提取到C中去。

体会

实际上,引用是别名,一旦绑定到一个变量,这个引用就不可能再绑定到别的变量了。
引用在其整个声明周期内只指向当初绑定的变量,而且永远不会指向别的变量,对这个引用做的所有操作,都是对它绑定的变量做的操作。

指针不同,指针初始化的过程中可以指向对象 A,后续还可以指向对象 B,甚至还可以为空指针。

特此记录这个对引用理解不到位的错误,以供反省。

以上是关于C++ 引用踩的坑的主要内容,如果未能解决你的问题,请参考以下文章

最近发现一个数据库,好像可以用,于是做了一个调查,把一般常用的和可能踩的坑都查了一下方法,记录了一下,以后可以使用.

Java面试80%的人都会踩的坑,你知道几种?

django使用过程的中踩的坑

初次使用antd-mobile开发时踩的坑

ArrayList与HashMap踩的坑

初级程序员易踩的 7 大坑!全中!