在 C++ 中,如果我获取并返回变量的地址,然后调用者立即取消引用它,编译器会可靠地优化这两个操作吗?
我问的原因是我有一个数据结构,其中使用类似于 std::map 的接口,其中 find() 返回指向值的指针(迭代器),并返回 NULL (没有简单的 .end()等价)表示尚未找到该值。
我碰巧知道存储的变量是指针,所以即使我直接返回值,返回 NULL 也可以正常工作,但似乎返回指向该值的指针更通用。 否则,如果有人试图在那里存储实际上为 0 的 int,数据结构会声称它不存在。
但是,我想知道这里是否有任何效率损失,因为编译器应该优化掉那些只会撤销彼此影响的操作。 问题是两者被函数返回分隔开,所以它可能无法检测到它们只是相互撤消。
最后,拥有一个仅返回值的私有成员函数和一个仅获取值地址的内联公共成员函数怎么样? 那么至少地址/取消引用操作会一起发生,并且有更好的机会被优化,而 find() 函数的整个主体不是内联的。
私人: V _find(键) { ... // 几十行... } 民众: 内联 V* find(key) { 返回 &_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);
_find
返回类型为 V
的临时对象。 find
然后尝试获取临时地址并将其返回。临时物品不会持续很长时间,因此得名。所以_find
返回的临时值在获得其地址后将被销毁。因此 find
将返回一个指向先前销毁的对象的指针,这是不好的。
无论哪种方式我都见过。这实际上取决于编译器和优化级别。即使它确实被内联,我也见过编译器不会优化它的情况。
查看它是否得到优化的唯一方法是实际查看反汇编。
您可能应该做的是制作一个手动内联它们的版本。然后对其进行基准测试,看看是否确实获得了明显的性能提升。如果不是,那么整个问题就没有意义了。
您的代码(即使是第二个版本)已损坏。
_find
返回一个 V
,find
在返回其地址之前立即销毁它。
如果
_find
返回一个 V&
到一个比调用更长的对象(从而生成正确的程序),那么取消引用将是一个无操作,因为引用与机器代码级别的指针没有什么不同。