2
#include <array>
#include <iostream>

using namespace std;

struct SimpleDebugger
{
    SimpleDebugger(int val = 0) : x(val) {
        cout << "created" << endl;
    }

    SimpleDebugger(const SimpleDebugger &that) : x(that.x) {
        cout << "copied" << endl;
    }

    ~SimpleDebugger() {
        cout << "killed!" << endl;
    }

    int getX() const {
        return x;
    }

    void setX(int val) {
        x = val;
    }

private:
    int x;
};

array<SimpleDebugger, 3> getInts(int i)
{
    array<SimpleDebugger, 3> a;
    a[0].setX(i);
    a[1].setX(i + 1);
    a[2].setX(i + 2);
    cout << "closing getInts" << endl;
    return a;
}

SimpleDebugger (*getIntsArray(int i)) [3] {
    typedef SimpleDebugger SimpleDebugger3ElemArray [3];
    SimpleDebugger3ElemArray *sd = new SimpleDebugger3ElemArray[1];
    (*sd)[0].setX(i);
    (*sd)[1].setX(i + 1);
    (*sd)[2].setX(i + 2);
    cout << "closing getIntsArray" << endl;
    return sd;
}

ostream& operator << (ostream& os, const SimpleDebugger &sd) {
    return (cout << sd.getX());
}

int main() {
    auto x = getInts(5);
    cout << "std::array = " << x[0] << x[1] << x[2] << endl;
    auto y = getIntsArray(8);
    cout << "Raw array = " << (*y)[0] << (*y)[1] << (*y)[2] << endl;
    delete [] y;
}

Output

created
created
created
closing getInts
std::array = 567
created
created
created
closing getIntsArray
Raw array = 8910
killed!
killed!
killed!
killed!
killed!
killed!

I tried this above program to see how convenient it is to use std::array over raw arrays, I know that avoiding old-style arrays is good style and even better is to use std::vector.

I'd like to know what happens under the hood in case of std::array, when the function getInts() returns. In case of the raw arrays, I know that it's a pointer copy and the onus of cleaning it up falls on the callee. In std::array this doesn't happen, but how does it internally store the data and how does the copy happen?

2
  • 1
    If you are using g++, try the test again with -fno-elide-constructors for another possible output. Commented Jan 24, 2013 at 19:35
  • @Robᵩ Wow, shows 6 "copied", thanks for the flag! Commented Jan 24, 2013 at 19:38

1 Answer 1

8

std::array is an aggregate, containing an array as its only data member. Copying or moving one will copy or move each element of the array into the new array.

In your case the copy is being elided when it's returned from the function; under the hood, the array is created in automatic storage in main, and the function fills in that array.

Sign up to request clarification or add additional context in comments.

14 Comments

+1 Doesn't this property of std::array make it less performant that old-style arrays?
@legends2k: It's exactly as perfomant as a built-in array for everything a built-in array can do. It's also copyable and movable.
I think I get it, one would never return a built-in array, or simply one can't rather, and just becasue std::array can be returned, returning it would make it less preformant as would be the case with any container type. Am I right in inferring this?
@legends2k: Indeed, move semantics and copy/move elision (or RVO if you prefer) are two different phenomena. Values returned from a function will be moved if possible, so there's no need to use std::move; and the compiler should elide the copy/move whenever it can.
Clarified now, and thanks for replying to all my comments patiently :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.