在C ++中,如果我得到并返回变量的地址,然后调用者立即取消引用它,编译器是否会可靠地优化这两个操作?
我问的原因是我有一个数据结构,我使用类似于std :: map的接口,其中find()返回一个值的指针(迭代器),并返回NULL(没有简单的.end ()等效)表示尚未找到该值。
我碰巧知道存储的变量是指针,所以即使我直接返回值,返回NULL也能正常工作,但似乎返回指向该值的指针更为通用。否则,如果有人试图在那里存储一个实际为0的int,那么数据结构会声称它不在那里。
但是,我想知道这里的效率是否有任何损失,因为编译器应该优化掉那些只能消除彼此影响的行为。问题是两者被函数返回分开,所以可能无法检测到它们只是相互撤消。
最后,如果有一个私有成员函数只返回值,那么内联公共成员函数只接受值的地址。然后至少地址/解除引用操作将一起发生并且更有可能被优化,而find()函数的整个主体没有内联。
<击> 撞击>
<击> 击>private: V _find(key) { ... // a few dozen lines... } public: inline V* find(key) { return &_find(key); } std::cout << *find(a_key);
这将返回指向临时的指针,我没有想到。与此类似的唯一事情是在_find()中进行大量处理并执行最后一步并在find()中返回指针以最小化内联代码的数量。
private:
W* _find(key) {
... // a few dozen lines...
}
public:
inline V* find(key) {
return some_func(_find(key)); // last steps on W to get V*
}
std::cout << *find(a_key);
或者正如另一位回应者提到的那样,我们可以在原始版本中返回对V的引用(再次,不知道为什么我们乍看之下都对琐碎的东西视而不见......参见讨论。)
private:
V& _find(key) {
... // a few dozen lines...
}
public:
inline V* find(key) {
return &_find(key);
}
std::cout << *find(a_key);
答案 0 :(得分:2)
_find
返回V
类型的临时对象。 find
然后尝试获取临时地址并将其返回。临时对象不会持续很长时间,因此得名。因此_find
返回的临时值将在获取其地址后被销毁。因此find
将返回一个指向先前被破坏的对象的指针,这是不好的。
答案 1 :(得分:1)
我已经看到过这种情况。这实际上取决于编译器和级别优化。即使它被内联,我也看到了编译器不会优化它的情况。
查看它是否确实优化的唯一方法是实际查看反汇编。
您应该做的是创建一个手动内联它们的版本。然后对其进行基准测试,看看你是否真的获得了显着的性能提升。如果没有,那么这整个问题都没有实际意义。
答案 2 :(得分:1)
你的代码(即使是第二个版本)也被破坏了。 _find
会返回V
,find
会在返回地址之前立即销毁。
如果_find
将一个V&
返回给一个比调用更长的对象(从而生成一个正确的程序),那么取消引用将是一个无操作,因为引用与指针没有区别在机器代码级别。