开发者

In C++ if a pointer is returned and immediately dereferenced, will the two operations be optimized away?

In C++ if I get and return the address of a variable and the caller then immediately dereferences it, will the compiler reliably optimize out the two operations?

The reason I ask is I have a data structure where I'm using an interface similar to std::map where find() returns a pointer (iterator) to a value, and returns NULL (there is no trivial .end() equivalent) to indicate that the value has not been found.

I happen to know that the variables being stored are pointers, so returning NULL works fine even if I returned the value directly, but it seems that returning a pointer to the value is more general. Otherwise if someone tried to store an int there that was actually 0 the data structure would claim it isn't there.

However, I'm wondering if there's even any loss in efficiency here, seeing as the compiler should optimize away actions that just undo the effect of each other. The problem is that the two are separated by a function return so maybe it wouldn't be able to detect that they just undo each other.

Lastly, what about having one private member function that just returns the value and an inline public member function that just takes the address of the value. Then at least the address/dereference operations would take place together and have a better chance of being optimized out, while the whole body of the find() function is not inlined.

private:
V _find(key) {
   ... // a few dozen lines...
}


public:
inline V* find(key) {
    return &_find(key);
}

std::cout << *find(a_key);

This would return a pointer to a temporary, which I didn't think about. The only thing that can be done similar to this is to do a lot of processing in the _find() and do the last开发者_如何学运维 step and the return of the pointer in find() to minimize the amount of inlined code.


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);

Or as yet another responder mentioned, we could return a reference to V in the original version (again, not sure why we're all blind to the trivial stuff at first glance... see discussion.)


private:
V& _find(key) {
   ... // a few dozen lines...
}


public:
inline V* find(key) {
    return &_find(key);
}

std::cout << *find(a_key);


_find returns a temporary object of type V. find then attempts to take the address of the temporary and return it. Temporary objects don't last very long, hence the name. So the temporary returned by _find will be destroyed after getting its address. And therefore find will return a pointer to a previously destroyed object, which is bad.


I've seen it go either way. It really depends on the compiler and the level optimization. Even when it does get inlined, I've seen cases where the compiler will not optimize this out.

The only way to see if it does get optimized out it is to actually look at the disassembly.

What you should probably do is to make a version where you manually inline them. Then benchmark it to see if you actually get a noticeable performance gain. If not, then this whole question is moot.


Your code (even in its second incarnation) is broken. _find returns a V, which find destroys immediately before returning its address.

If _find returned a V& to an object that outlives the call (thus producing a correct program), then the dereference would be a no-op, since a reference is no different to a pointer at the machine code level.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜