1

In my database accessing code, I wish to write a method:

variant_t GetQueryRows (...)

I would like to call it:

const variant_t result = GetQueryRows (...)

Although I can do this, the copying of the variant_t shows rather high in my profiler results. So I need to ensure that the variant_t is not copied. There is no move constructor or move assign in variant_t, and I cannot modify the source of variant_t in order to add one.

Is there anything I can do in Visual Studio 2012 using C++, aside from the obvious thing of returning the 'result' via an out parameter?

Brian Campbell
  • 322,767
  • 57
  • 360
  • 340
Coder_Dan
  • 1,815
  • 3
  • 23
  • 31
  • Thanks to everyone for your helpful answers. It sounds like the key thing here is that GetQueryRows calls onto ADO methods that throw exceptions, so this will prevent elision. – Coder_Dan Nov 15 '13 at 15:31

3 Answers3

4

There's nothing you can do to guarantee it. If possible, the compiler will generally elide this copy via return value optimization, but there are several caveats.

Within GetQueryRows, you should have only one named variable that is returned, from only one point in the function; multiple returns, or returns that may return one value or another, break return value optimization. You cannot throw any exceptions.

If you want to guarantee the behavior, using an output parameter is the only reliable way.

Brian Campbell
  • 322,767
  • 57
  • 360
  • 340
  • 3
    N.B. throwing exceptions prevents MSVC from doing copy elision, but it doesn't have to in principle, and doesn't with G++ or Clang – Jonathan Wakely Nov 15 '13 at 15:32
  • Thanks Brian & @Jonathan for pointing out these details regarding exceptions. That's useful information. – Coder_Dan Nov 15 '13 at 15:37
  • @JonathanWakely You're right, I was merely referring to Microsoft's guidelines, not general guidelines across compilers. – Brian Campbell Nov 15 '13 at 17:03
2

Compilers will elide copying that by an optimization called return value optimization. They will be applied by compiler if it's possible, you can not force it. In addition you can use move semantics to avoid deep copies.

Don't make your program's logic rely on this kind of optimization. But, write your code somehow so that the compiler will be encouraged to apply these optimizations.

Community
  • 1
  • 1
masoud
  • 55,379
  • 16
  • 141
  • 208
1

Copy ellision by return value optimization will likely occur if GetQueryRows is structured thusly:

const variant_t GetQueryRows() {
    variant_t result;  // Exactly one declaration of return value
    ...                // arbitrary code
    return result;     // Exactly one return statement.
}

Reference: http://msdn.microsoft.com/en-us/library/ms364057(v=vs.80).aspx

Robᵩ
  • 163,533
  • 20
  • 239
  • 308