Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Returning an array in C++

Name: Anonymous 2009-10-26 20:39

PLEASE /prog/ help me out here. I've read and tested at least 5 "answers" to my question that I've found on google, but I can't get any of them to work. You guys are better than them though, right?

I wanted to call an array by reference in a function. Then, I learned that that was impossible. I tried returning the array, but you can't do that either.

Apparently, I need to do some shit with pointers to return the array. How the fuck do I do this?

Name: Anonymous 2009-10-27 16:11

>>39
calloc zeroes memory iirc

Name: Anonymous 2009-10-27 16:43

looks like you're right. w.e, I don't care, I'm a faggot and use new/delete anyway, I don't care about malloc/calloc/fuckloc

Name: Anonymous 2009-10-27 17:18

>>38
Superior implementation. If you're programming Sepples, you'd better use templates wherever possible.
template<class T>
T* getArray(int length) {
    return new T[length];
}

Name: Anonymous 2009-10-27 17:19

>>43
Templates make me RAGE

Name: Anonymous 2009-10-27 17:38

>>44
template<unsigned int n> struct fib
{
    static const unsigned int result=fib<n-1>::result+fib<n-2>::result;
};

template<> struct fib<1>
{
    static const unsigned int result=1;
};

template<> struct fib<0>
{
    static const unsigned int result=0;
};

int main()
{
    std::cout<<"fib<1>="<<fib<1>::result<<'\n';
    std::cout<<"fib<2>="<<fib<2>::result<<'\n';
    std::cout<<"fib<3>="<<fib<3>::result<<'\n';
    std::cout<<"fib<4>="<<fib<4>::result<<'\n';
    std::cout<<"fib<5>="<<fib<5>::result<<'\n';
    return 0;
}

Name: Anonymous 2009-10-27 17:45

>>44
How come? They're C++'s best (only good) feature. Are you just mad that C++ has a good feature?

Name: Anonymous 2009-10-27 18:10

>>46
No because a giant hack for a giant hack of a language

Name: Anonymous 2009-10-27 21:07

>>1
Simple:

return new int[5];

Of course you want that memory to be checked, transferable and exception safe, so you do this:

return std::auto_ptr<int>(new int[5]);

But that's not right, wrong delete. Boost to the rescue:

return std::tr1::shared_array<int>(new int[5]);

You should be using a vector anyway, but you don't want to be copying the vector, so you need a vector pointer:

return std::auto_ptr<std::vector<int>>(new std::vector<int>(5, 0));

Now you want the smart pointer to be thread safe and container safe of course, so you do this:

return std::tr1::shared_ptr<std::vector<int>>(new std::vector<int>(5, 0));

But you should of course allow configuring the allocation strategy, and it also needs to be exception safe, so you do something like this:

template <class Alloc>
std::tr1::shared_ptr<std::vector<int>> makeArray() {
  Alloc::rebind<std::vector<int>>::other alloc;
  std::tr1::shared_array<std::vector<int>> ret(alloc.allocate(1));
  alloc.construct(ret.get(), std::vector<int>(5, 0));
  return ret;
}




...In C, you take an pointer parameter, and modify the array in place. Crazy C programmers, always doing things the hard way...

Name: Anonymous 2009-10-27 22:14

I'm actually planning to write a program to combine the best features of Lisp and C++ by allowing you to define and use Lisp macros in C++ code. Instead of writing pair<int> x;, you'd just write (pair int) x;, and pair would be a Lisp macro that expanded it as appropriate. It'll be awesome!

Name: Anonymous 2009-10-27 22:20

...In C, you take an pointer parameter, and modify the array in place.
...and don't get any of the features you spent your whole post including. Write an equivalent C program, why don't you?

Name: Anonymous 2009-10-27 22:38

int *f(){
    int i = 6;
    return &i;
}


This probably isn't technically correct, but I only compile with gcc so it doesn't matter.

Name: Anonymous 2009-10-27 22:51

>>51
That's extremely bad and also wrong. Why do you idiots keep trying to return the addresses of local variables? Even gcc, which you claim to use, will warn you about this by default.

t.c:4: warning: function returns address of local variable

Name: Anonymous 2009-10-27 22:59

>>51
int* f()
{
    int i = 6;
    return &i;
}
void g()
{
     int destroy_the_stack[1000];
}
int main()
{
    int* a = f();
    g();
    cout << *a << endl; //uh-oh spagetti-o's
    return 0;
}

Name: Anonymous 2009-10-27 23:23

>>53
No one does this anyways. >>51-sensei's way is good enough, and is actually the fastest come run-time.  I would prefer speed over taking care of some random boundary case like >>53-chan's anyday.

Name: Anonymous 2009-10-27 23:29

>>54
0/10. I award you no points, and may God have mercy on your soul.

Name: Anonymous 2009-10-27 23:30

>>54
Setting yourself up for failure. I hope you don't program flight control computers

Name: Anonymous 2009-10-27 23:38

>>56
Haha, I am glad I don't.  I write games in C++.  I am currently writing 3 games, and I am hoping to release them in 2010 (probably for Christmas.  One my have to wait until 2011) Unlike you, I can actually program, make money, and have fun at the same time, and in games every bit of optimization is important.

Name: Anonymous 2009-10-27 23:41

>>57
HOLY SHIT IT'S MAT DICKIE

Name: Anonymous 2009-10-27 23:43

>>58
Don't be silly, Mat Dickie isn't real

Name: Anonymous 2009-10-27 23:47

>>59
o ok

Name: Anonymous 2009-10-28 0:29

>>57
Wow, you're pretty awesome Anonymous.

>>53
Interestingly your destroy_the_stack array doesn't actually destroy the stack. You just declared some stack space which is never actually used. Try destroy_the_stack[0]=0;.

>>50
Way to not get the point. These are not features, they are anti-features. They are a massive overcomplication of something that should be extremely simple.

This thread is like the twilight zone. Since when does /prog/ like sepples?

Name: Anonymous 2009-10-28 0:33

>>61
you're right, however on my gcc it was sufficient to corrupt the 6 located at a, so I went with it. your mileage may vary based on your compiler

Name: Anonymous 2009-10-28 0:36

Here's a more to-the-point demo prog based on >>61's suggestion (and one which is definitely *not* a boundary case)
int* f()
{
    int i = 6;
    return &i;
}
void g()
{
     int destroy_the_stack = 9;
}
int main()
{
    int* a = f();
    g();
    cout << *a << endl; //uh-oh spaghetti-o's -- displays 9
    return 0;
}

Name: Anonymous 2009-10-28 0:40

>>61
Trolled by an incompetent troll

Name: Anonymous 2009-10-28 0:41

>>54
Oh holy fuck, I didn't actually fully interpret the depth of this post the first time around. You think that having a pointer to a stack variable and then calling a function that overwrites it is a 'random boundary case'?

Honestly. You are seriously fucking retarded. You know when you build -Wall -pedantic and the compiler gives you hundreds of warnings? Those aren't a joke. You are seriously fucking up. In my last two jobs, I introduced the policy of building everything -Wall, and it all has to come out no warnings to ship.

Also what the fuck makes you think >>51 is fastest at run-time? It doesn't fucking do anything except give you a pointer to a literal, applied dangerously somewhere on the stack. None of these examples even make any sense. It certainly hasn't allocated an array; it has fuck all even to do with arrays.

And 'allocating an array' is an extremely generic concept; you can't just point at some code and say which is fastest. How big does the array need to be? Is it thread-local? Small? Function scoped? Then you can probably alloca() it. Is it small but shared? Consistent size? You can maybe pool it. Threaded? Add locks to the pool. Is it fairly large? malloc(). Quite large? mmap().

Honestly though all of this is superfluous. malloc() is going to be your best bet in almost all situations, since a good malloc() does all the above for you except stack allocations (which often cause more problems than they solve). You can never figure out the best way to do these things besides profiling, and honestly you always have bigger bottlenecks (like the fact that you have allocations outside of loading in the first place). The allocator is all powerful; trust the allocator.

Please tell me what your games are so I can avoid their bugs and security vulnerabilities.

Name: Anonymous 2009-10-28 0:44

>>65
A new is fine too

Name: Anonymous 2009-10-28 0:48

>>66
Not for arrays.

Name: Anonymous 2009-10-28 0:50

>>67
Do go on

Name: Anonymous 2009-10-28 1:03

>>68
Well, it's garbage for anything other than pointers or primitive types simply because of constructors. If you're trying to set up some kind of pool (say a pool of particle objects), to use new[] you have to subvert the usual constructor/destructor scheme and provide your own init/destroy functions. This is dumb. You're much better off malloc()'ing the memory, and using in-place construction/destruction, so you can have proper constructors and destructors for your objects without the associated allocation costs.

As far as primitive types go, there are safer ways. These sorts of arrays are usually either fixed compile-time sizes, so you're better off having them as a field of a struct/class, or for growable arrays, so you're better off using some sort of vector class (or std::vector if you're lazy). And no, there is no overhead to an std::vector of primitives aside from the size of the array (which, if you're sizing dynamically, you generally need to have stored anyway).

Name: Anonymous 2009-10-28 1:21

>>69
To add to this, boost has a memory pool built in that does exactly this, because getting this all correct and exception-safe in sepples can actually get quite complicated (easy to fuck up). As usual, something that should be simple is instead excruciating, but because it has a shitty prefab template for you to use people will cheer about how powerful their language and library is. Go sepples!

Name: Anonymous 2009-10-28 1:35

>>50
Love to!

int* make_array(void* (*alloc)(size_t)) {
  return (int*) (*alloc)(sizeof(int) * 5);
}


Check that shit out! Custom allocator and everything. Pretty bitching, right? It doesn't have the smart pointers, but guess what, you don't need them in C because there's no such thing as exceptions (nor threads. Remember kids, threads are evil. Isolate processes; avoid shared memory; communicate through pipes; the UNIX way). Memory management in C is pretty damn easy.

Name: Anonymous 2009-10-28 2:01

>>71
I think I had the UNIX equivalent of an orgasm

Name: Anonymous 2009-10-28 2:11

>>72

phiber@scout:~$ cum > filthy.sock

Name: Anonymous 2009-10-28 2:12

>>72
[Anonymous@/prog/ ~]$ yes oh yes

Name: Anonymous 2009-10-28 2:15

>>61
Since when does /prog/ like sepples?
Much as I hate Sepples, I hate people who Sepple wrong even more.

Name: Anonymous 2009-10-28 5:43

>>73
Lol I do that sometimes if I can't find a tissue. Else underwear

Name: Anonymous 2009-10-28 6:07

>>73
Why is sock an attribute of filthy, instead of the other way around
Sock.filthy = True

Name: Anonymous 2009-10-28 6:13

>>77
no no no your doing it wrong. The Sock object should implement the Filthy interface if it's filthy

Name: Anonymous 2009-10-28 6:24

>>78
Enjoy your Robust Scalable Turnkey Solutions

Name: Anonymous 2009-10-28 6:58

>>78
You can't dynamically implement an interface depending on whether the sock is filthy or not though. Your move.

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List