0

Short version:

If my object contains a std::vector, do the same rules of thumb apply to returning that object by value as to returning the vector by value?

Does this change in C++11, which I understand "guarantees" returning a vector by value is fast?

Long version:

I have a small wrapper class that contains a std::vector.

class gf255_poly
{
    public:

        // ... Lots of polynomial methods

    protected:
        std::vector<unsigned char> p;
};

I'd like to return instances of this class from certain functions such as:

// Performs polynomial addition in GF(2^8). 
gf255_poly gf255_poly_add(const gf255_poly &poly1, const gf255_poly &poly2) const
{
    // Initialize:
    gf255_poly dst = poly1;

    // Add all coefficients of poly1 to poly2, respecting degree (the usual polynomial addition)
    for (int deg = 0; deg <= poly2.degree(); deg++)
        dst.addAt(deg, poly2.coef(deg));

    return dst;
}

I've found plenty of information on how to return a member vector and whether it is still a bad design pattern to return a std::vector (it seems that that's fine under most circumstances). I haven't found much that includes vectors that are members of larger objects, though.

Does the same advice apply? Do I need to do anything special in my copy constructor to help ensure return value optimization?

Are the answers to this question different for different versions of the C++ standard?

Community
  • 1
  • 1
Bear
  • 345
  • 4
  • 16
  • If you want to be sure, write move constructor for your gf255_poly can help. – apple apple Sep 09 '16 at 15:04
  • @appleapple: NRVO is allowed to ignore the move constructor. – Bathsheba Sep 09 '16 at 15:04
  • It really depends on what the return value is being returned to. If it is an already created item then you have a copy/move assignment. If it is a new object then most likely NRVO will kick in. – NathanOliver Sep 09 '16 at 15:05
  • 1
    Just a point -- sometimes you can overdo "hand optimization" to the point where you're actually not helping make the code run faster. The compiler's optimizer is built to recognize certain patterns in the code, and if you thwart the compiler's optimizer, you can make the code run slower than it should. Just write the code in the most understandable manner, and then profile (an optimized version) if it is detected that a particular spot in the program is slow. – PaulMcKenzie Sep 09 '16 at 15:09
  • @Bathsheba I think "be sure of performance", so ignore the move constructor (and use RVO) is not a problem here. – apple apple Sep 09 '16 at 15:14

3 Answers3

2

Your writing gf255_poly dst = poly1; followed by return dst; is exploiting Named Returned Value Optimisation (NRVO).

This is a more recent innovation than Returned Value Optimisation but is certainly implemented by modern compilers, irrespective of the C++ standard they are targeting. To be absolutely clear, NRVO is not a C++11 specific thing.

Exploiting NRVO is not a bad design choice as using it makes source code easier to read and maintain.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
1
  • < c++11, you should rely on the compiler to do Return Value Optimization.

  • >= c++11, you can use move semantics to keep your code fast even if the compiler fail to (or can't) do the RVO.

You need to have (maybe default) move constructor in your class to enable this behavior.

You can also use =default on move constructor.(but visual studio 2008 seems do not have this feature)

apple apple
  • 10,292
  • 2
  • 16
  • 36
0

It depends on how smart is your compiler (usually a lot). So it should be "safe" on whatever modern compiler you are using.

xmas79
  • 5,060
  • 2
  • 14
  • 35