首先请注意,在 C++ 中,与 Java 不同,用户可以定义值类型。这意味着一个 routing_entry 有 2^32 * 2^32 * 2^8 个可能的值。如果您愿意,您可以将 routing_entry 视为 72 位原始类型,尽管您必须小心类比。
因此,在 Java 中,route 可以为空,routing_entry 变量有 2^32 * 2^32 * 2^8 + 1 个有用的不同值。在 C++ 中,它不能为空。在 Java 中,“空”可能意味着返回一个空引用。在 C++ 中,只有指针可以为空,routing_entry 不是指针类型。所以在你的代码中,在这种情况下,“空”意味着“我不知道这个东西有什么价值,因为我从来没有初始化它或分配给它”。
在 Java 中,routing_entry 对象将在堆上分配。在 C++ 中你不想这样做,除非你必须这样做,因为 C++ 中的内存管理很费力。
你有几个(好的)选择:
1) 向路由条目添加一个字段,以表明它已被初始化。由于实现的填充和对齐要求,这可能不会使结构变得更大:
struct routing_entry {
unsigned long destSeq; // 32 bits on Win32. Could be different.
unsigned long nextHop // 32 bits on Win32. Could be different.
unsigned char hopCount; // 8 bits on all modern CPUs. Could be different.
unsigned char initialized; // ditto
};
为什么不使用布尔值?因为该标准有助于sizeof(bool) != 1。完全有可能将 bool 实现为 int,特别是如果您有一个旧的 C++ 编译器。这会使你的结构更大。
然后确保在你的函数中使用 0 值初始化结构,而不是堆栈上的任何垃圾:
routing_entry Cnode_router_aodv::consultTable(unsigned int destinationID ) {
routing_entry route = {};
if ( routing_table.find(destinationID) != routing_table.end() )
route = routing_table[destinationID];
return route; // will be "empty" if not found
}
并确保映射中的所有条目都将初始化字段设置为非零。调用者然后检查初始化。
2) 使用现有字段的“神奇”值作为标记。
假设你从不处理 hopCount 为 0 的路由。那么只要你像上面那样初始化 0,调用者就可以检查 hopCount != 0。类型的最大值也是很好的标志值 -由于您将路线限制为 256 跳,因此将它们限制为 255 跳可能不会造成任何伤害。调用者不必记住这一点,而是向结构添加一个方法:
struct routing_entry {
unsigned long destSeq; // 32 bits
unsigned long nextHop // 32 bits
unsigned char hopCount; // 8 bits
bool routeFound() { return hopCount != (unsigned char)-1; }
};
然后你会这样初始化:
routing_entry route = {0, 0, -1};
或者如果您担心将来更改字段的顺序或数量时会发生什么:
routing_entry route = {0};
route.hopCount = -1;
调用者会这样做:
routing_entry myroute = consultTable(destID);
if (myroute.routeFound()) {
// get on with it
} else {
// destination unreachable. Look somewhere else.
}
3) 调用者通过指针或非常量引用传入routing_entry。被调用者将答案填入其中,并返回一个值,指示它是否成功。这通常称为“输出参数”,因为它有点模拟返回 routing_entry 和布尔值的函数。
bool consultTable(unsigned int destinationID, routing_entry &route) {
if ( routing_table.find(destinationID) != routing_table.end() ) {
route = routing_table[destinationID];
return true;
}
return false;
}
调用者:
routing_entry route;
if (consultTable(destID, route)) {
// route found
} else {
// destination unreachable
}
顺便说一句,在使用地图时,您的代码会查找 ID 两次。你可以避免这种情况
如下所示,尽管它不太可能对您的应用性能产生明显影响:
map< unsigned long int, routing_entry >::iterator it =
routing_table.find(destinationID);
if (it != routing_table.end()) route = *it;