Passing around fixed-size arrays in C++?

24,122

Solution 1

Using C++0x, the almost finalized new C++ standard (already implemented in latest gcc and msvc IIRC), you can do it exactly as you want! Simply use std::array instead of int[3].

std::array<int, 3> array_func()
{
    return {1,1,1};
}

int main(int argc,char * argv[])
{
    std::array<int, 3> point = array_func();
}

Solution 2

Put the array into a struct. boost::array is such a package:

boost::array<int, 3> array_func() {
  boost::array<int, 3> a = {{ 1, 1, 1 }};
  return a;
}

int main() {
  boost::array<int, 3> b = array_func();
}

Quick and dirty:

template<typename E, size_t S>
struct my_array {
  E data[S];
};

Notice how you can use aggregate initialization syntax.

Solution 3

You can wrap it in a struct, to make it returnable by value:

struct Vec3
{
  float x[3];
}

Vec3 array_func()
{
  Vec3 x = { 1.f, 1.f, 1.f };

  return x;
}

I don't think you can use the array initializer syntax directly in the return statement. Of course you could introduce a constructor (structs are just classes with all members public, after all):

struct Vec3
{
  Vec3(a, b, c)
  {
    x[0] = a;
    x[1] = b;
    x[2] = c;
  }

  float x[3];
}

Vec3 array_func()
{
  return Vec3(1.f, 1.f, 1.f);
}

Solution 4

you can't return a fixed size array in C++. you may return a pointer to int (which would be used as an array) but that would require allocating the array on the heap using new.

anyway, you can pass your array as an argument to your function:

void array_func( int result[3])
{
    result[0] = 1;
    result[1] = 1;
    result[2] = 1;
}

int main(int argc,char * argv[])
{
    int point[3];
    array_func( point );
}

however, this looks more like C than C++...

Share:
24,122
static_rtti
Author by

static_rtti

Creator of autojump, the fastest way to move around your filesystem from the command line.

Updated on November 19, 2020

Comments

  • static_rtti
    static_rtti over 3 years

    Basically I'd like to do something like that:

    int[3] array_func()
    {
        return {1,1,1};
    }
    
    int main(int argc,char * argv[])
    {
        int[3] point=array_func();
    }
    

    But that doesn't seem legal in C++. I know I can use vectors, but since I know the size of the array is a constant, it seems like a loss of performance is likely to occur. I'd also like to avoid a new if I can, because allocating stuff on the stack is easier and also likely to improve performance.

    What's the solution here?

  • Christian
    Christian over 14 years
    new isn't needed necessarily. It's also possible to make the array static inside the array_func function (if that's possible depends of course)
  • sbi
    sbi over 14 years
    Um, isn't that 3 in the parameter declaration ignored?
  • sbi
    sbi over 14 years
    That would be the best answer except that such a struct already exists: stackoverflow.com/questions/1755000/1755017#1755017
  • Adrien Plisson
    Adrien Plisson over 14 years
    yes you are right, finally, i am not even sure it compiles. you may have to omit the array size in the declaration of the function...
  • Ankit Roy
    Ankit Roy over 14 years
    @Adrien: It will compile, but the compiler will ignore the number 3, silently "decaying" the type of result from int result[3] to int *result (usually without even giving a warning). Which is a bit sneaky of the compiler if you ask me ;)
  • Adrien Plisson
    Adrien Plisson over 14 years
    ...and would also open the door to a buffer overflow, but that's how C works. anyway, when used on purpose, this solution still works.
  • static_rtti
    static_rtti over 14 years
    I chose it as the best answer because it answers my question, plain and simple, without pushing a library I didn't ask for. Not that litb's answer is bad, I just found unwind's answer a bit clearer.
  • sbi
    sbi over 14 years
    "...pushing a library I didn't ask for..." Well, we're talking boost here, not just some library. Anyway, there's a very good chance your standard lib implementation comes with std::tr1::array (C++03 or TR1) or even std::array (C++1x), which is exactly the same. (Which goes to show that boost isn't just another library. It's a testbed for the next C++ standard, founded by std committee members for exactly that reason, has very high quality standards and demanding reviews, and it's contributing a whole lot of stuff to the next standard library.)
  • KomodoDave
    KomodoDave almost 12 years
    I don't understand why this is upvoted so much, using standard language features (in this case, a simple struct) is much cleaner and quicker than invoking boost. Though I do recommend the templated struct used here - this is the simplest solution that's most reusable, and what I would have done.
  • KomodoDave
    KomodoDave almost 12 years
    @sbi Use of boost is entirely unnecessary here, and suggesting that using a library is preferable to using standard language features, particularly when the latter takes far fewer keystrokes, is absurd.
  • Johannes Schaub - litb
    Johannes Schaub - litb almost 12 years
    @KomodoDave are you aware that you can do sed,boost,std, in my above snippet and don't even need "a simple struct"? hooray, we are're landed at 2011! sometimes invoking the "bloated boost" (i suppose) can turn out to eventually lead to less bloat than reinventing the wheel.
  • jweyrich
    jweyrich almost 12 years
    @KomodoDave I would suggest downvoting wrong answers, and those that do not really answer the question. This answer seems ok to me.
  • sbi
    sbi almost 12 years
    @KomodoDave: Um. You might want to look at my comment's date. Back then, there was no std::array. Nowadays, I'd certainly use that. (However, just as I said, it came out of boost.)
  • KomodoDave
    KomodoDave almost 12 years
    I'm downvoting because I think the suggestion of using boost in this case is a bad decision. If the only suggestion were the templated struct, this would be my preferred answer.
  • KomodoDave
    KomodoDave almost 12 years
    I also think the comment "Quick and dirty" for the proper use of a templated struct is inappropriate. My downvote has nothing to do with "bloated boost" as Johannes suggests, in fact the one thing I do like about boost is you only include what you need. I'll ignore the sarcastic 2011 comment, it does the OP no favours.
  • user2796283
    user2796283 over 8 years
    changing the signature of array_func to 'void array_func( int(&result)[3] )' prevents you from passing arrays that are not the right size to array_func