Phlar
Phlar

Reputation: 33

Can unused function-arguments become optimized away?

I'm trying to ensure an object - wrapped by a shared_ptr - is alive as long as a function is executed by passing it as value. However inside the function the object is not used at all, so I just want to use it for 'pinning':

void doSomething(std::shared_ptr<Foo>) {
    // Perform some operations unrelated to the passed shared_ptr.
}

int main() {
    auto myFoo{std::make_shared<Foo>()};
    doSomething(std::move(myFoo)); // Is 'myFoo' kept alive until doSomething returns?
    return 0;
}

I did check the behavior on different optimization-levels (GCC) and it seems that it works as intended, however I don't know whether the compiler still may optimize it away in certain scenarios.

Upvotes: 2

Views: 707

Answers (3)

Alan Birtles
Alan Birtles

Reputation: 36379

The compiler could optimise away the copying of an object into a function argument if the function is being inlined and if the copying has no side effects.

Copying a shared_ptr increments its reference count so it does have side effects so the compiler can't optimise it away (unless the compiler can prove to itself that not modifying the reference count has no effect on the program).

Upvotes: 0

Daniel Langr
Daniel Langr

Reputation: 23497

This very much depends on what the body of doSomething and Foo will actually look like. For instance, consider the following example:

struct X 
{
    ~X() { std::cout << "2"; };
};

void f(std::shared_ptr<X>) { std::cout << "1"; }

int main()
{
    auto p = std::make_shared<X>();
    f(std::move(p));
}

This program has the very same observable effect as:

int main()
{
  std::cout << "12";
}

and the order "12" is guaranteed. So, in the generated assembly, there may be no shared pointer used. However, most compilers will likely not perform such aggressive optimizations since there are dynamic memory allocations and virtual function calls involved internally, which is not that easy to optimize away.

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234645

You don't need to worry - the lifetime of the function argument at the call site is guaranteed to survive the function call. (This is why things like foo(s.c_str()) for a std::string s work.)

A compiler is not allowed to break that rule, subject to as if rule flexibility.

Upvotes: 6

Related Questions