24

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?

static_rtti
  • 53,760
  • 47
  • 136
  • 192
  • After the array_func() returns, the stack-allocated array will be lost, right? Therefore I don't think this is a good way to create and return arrays. I think your best bet is allocating it on the heap. P.S. I am no C++ expert, I wrote my own opinion on the matter. Feel free to correct :) – Doga Oruc Oct 31 '19 at 21:37

5 Answers5

31

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();
}
Didier Trosset
  • 36,376
  • 13
  • 83
  • 122
22

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.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 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 Jul 10 '12 at 21:53
  • @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. – Johannes Schaub - litb Jul 10 '12 at 22:00
  • 3
    @KomodoDave I would suggest downvoting wrong answers, and those that do not really answer the question. This answer seems ok to me. – jweyrich Jul 10 '12 at 22:01
  • 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 Jul 11 '12 at 18:54
  • 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. – KomodoDave Jul 11 '12 at 19:02
21

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);
}
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 4
    That would be the best answer except that such a struct already exists: http://stackoverflow.com/questions/1755000/1755017#1755017 – sbi Nov 18 '09 at 11:32
  • 7
    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. – static_rtti Nov 18 '09 at 12:56
  • 3
    "...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.) – sbi Nov 19 '09 at 09:21
  • 3
    @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. – KomodoDave Jul 10 '12 at 21:56
  • 1
    @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.) – sbi Jul 10 '12 at 22:13
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++...

Adrien Plisson
  • 22,486
  • 6
  • 42
  • 73
  • 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) – Christian Nov 18 '09 at 10:29
  • 1
    Um, isn't that `3` in the parameter declaration ignored? – sbi Nov 18 '09 at 11:31
  • 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... – Adrien Plisson Nov 18 '09 at 12:08
  • 1
    @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 ;) – j_random_hacker Nov 18 '09 at 12:18
  • ...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. – Adrien Plisson Nov 18 '09 at 12:38
  • 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 – user2796283 Feb 08 '16 at 09:10
0

boost::array is a wrapper for a stack-based array.

Note that stack allocation is only going to stay cheaper than using 'new' when you're not having to copy large arrays around.

Kylotan
  • 18,290
  • 7
  • 46
  • 74