Re: pass an array throuh a function

From: Leor Zolman (leor_at_bdsoft.com)
Date: 05/26/04

  • Next message: Arthur J. O'Dwyer: "[OT] Re: Tabs vs. Spaces"
    Date: Wed, 26 May 2004 09:22:34 -0400
    
    

    On Wed, 26 May 2004 19:37:55 +1000, "Chris \( Val \)"
    <chrisval@bigpond.com.au> wrote:

    >
    >"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
    >news:sCh0OTEckFtAFwGe@robinton.demon.co.uk...
    >| In message <cZQsc.114$%r.27073@nasal.pacific.net.au>, David White
    >| <no@email.provided> writes
    >| >It's not possible to pass an array to a function, at least not directly. If
    >| >you try, only the address of the first element is passed, in other words
    >| >a pointer.
    >|
    >| Not exactly true in C++. Consider:
    >
    >Ok, I'll bite ;-).
    >
    >| int const array_size(20);
    >| typedef float data[array_size];
    >|
    >| void show(data & d){
    >| for(int i(0); i != array_size; ++i){
    >| std::cout << d[i] << " ";
    >| }
    >| )
    >
    >Doesn't this just demonstrate a way of using a reference
    >to the pointer. You have still not passed the actual array
    >though - just a pointer to it's first element as 'David'
    >said, albeit this time by reference, no ?

    I'll join in the bite-fest ;-)

    This is an interesting point for me, "Mr. Newly Enlightened on What
    References /Really/ Are" from a thread in days gone by around here. I
    learned something then, and a bit more just now by toying with this issue.

    So here's a version of Francis' test program (show1 is his version of show)
    expanded to test your conjecture by adding versions of show() as follows:
            show2 takes a reference to a non-const pointer-to-float
            show2c takes a reference to a const pointer-to-float
            show3 takes a vanilla pointer-to-float

    #include <iostream>
    #include <iomanip>
    using std::cout;
    using std::endl;

    int const array_size(5);
    typedef float data[array_size];

    void show1(data & d) // Francis' version
    {
        cout << "in show1(), d = " << std::hex << d << endl;
        for(int i(0); i != array_size; ++i){
            std::cout << d[i] << " ";
        }
        cout << endl;
    }

    void show2(float * & d) // Chris's version
    {
        cout << "in show2(), d = " << std::hex << d << endl;
        for(int i(0); i != array_size; ++i){
            std::cout << d[i] << " ";
        }
        cout << endl;
    }

    void show2c(float * const& d) // Chris's with const
    {
        cout << "in show2(), d = " << std::hex << d << endl;
        for(int i(0); i != array_size; ++i){
            std::cout << d[i] << " ";
        }
        cout << endl;
    }

    void show3(float *d) // Leor's boring pointer version
    {
        cout << "in show3(), d = " << std::hex << d << endl;
        for(int i(0); i != array_size; ++i){
            std::cout << d[i] << " ";
        }
        cout << endl;
    }

    int main()
    {
        data x = {10, 20, 30, 40, 50};
        float *fptr = x;

        cout << "In main, x = " << std::hex << x << endl;

        show1(x); // OK, ref to array
        show2(x); // Error! Can't convert 'data' to float *&
        show2(fptr); // OK, CAN have ref to a "real" float *
        show2c(x); // OK, ref to const float *
        show3(x); // OK, ptr to float

        return 0;
    }

    show1 just does things the way they were before, and of course, works.

    show2 is set up as the version you suggested below, and does not compile.
    How can you have a reference to a pointer that doesn't actually "exist"?
    IOW, this is where the "reference-ness" of the parameter really stands out.
    There's no actual non-const pointer to bind that parameter to. You can't
    expect to, say, delete and then re-assign the pointer (as you describe),
    when there's no actual pointer to assign to. This actually makes sense to
    me, which is scary ;-)

    If you call show2 passing an actual, honest-to-goodness float *, however
    (as shown when I pass fptr), it compiles fine. Now the parameter can be
    bound to a non-const pointer-to-float directly.

    In the case of show2c, adding the const qualifier makes it possible for the
    compiler to generate a temporary pointer to the first element of the array
    and then have the function parameter be bound to it (I think...). So here,
    presumably, you /could/ call delete on that pointer (although it would be
    UB in this particular case, since the address wasn't obtained from new),
    but you still could not, of course, assign the result of a new expression
    to the pointer (since temporaries are const).

    Finally, you can call show3 the same way you call show1, by passing x
    "directly"; in the case of show3, the array name decays to a pointer in
    old-fashioned C-style.

    What a way to start the day, esp. after only 3.5 hours sleep ;-)
            -leor

    >void show( float*& d )
    > {
    > // ...
    > }
    >
    >Passing by reference in this way, would of course allow
    >us to delete the memory, and then re'new' the array within
    >the function to an alternate size, but we are always only
    >working with the pointer, no matter if it is passed by value
    >or reference aren't we ?
    >
    >| However what you cannot do is to pass an array by value
    >| unless you wrap it up in a class or struct.
    >
    >I thought this held true for arrays no matter what type of
    >passing idiom we chose ?
    >
    >Cheers.
    >Chris Val
    >

    -- 
    Leor Zolman --- BD Software --- www.bdsoft.com
    On-Site Training in C/C++, Java, Perl and Unix  
    C++ users: download BD Software's free STL Error Message Decryptor at:
       www.bdsoft.com/tools/stlfilt.html
    

  • Next message: Arthur J. O'Dwyer: "[OT] Re: Tabs vs. Spaces"

    Relevant Pages

    • Re: assert
      ... reference class instances the array can only contain pointers to the ... classes that are internally default public): reference classes and value ... via just its pointer. ... static void Assert(bool condition) ...
      (microsoft.public.dotnet.languages.vc)
    • Re: "Must instantiate controlled types at library level." Why?
      ... > The array bounds become unknown. ... > just the size of an pointer. ... It also show that operators attached to a reference type act ... > the compiler will stop creating copy constructors and warn you if you ...
      (comp.lang.ada)
    • Re: ByVal vs. ByRef
      ... But I still don't understand why I have to pass the TreeNode argument ByVal. ... I understand why passing it ByVal works. ... What is "the Value" of a reference variable? ... A "pointer" to the object. ...
      (microsoft.public.dotnet.languages.vb)
    • Re: assert
      ... value class valClass ... create the array POINTER. ... by passing JUST the pointer to rc it has virtually passed ... classes that are internally default public): reference classes and value ...
      (microsoft.public.dotnet.languages.vc)
    • Re: pointer/ref question
      ... reference" to generically indicate we're conveying the address of an ... to /me/ one can describe both of these situations as "passing ... the term "pass by pointer" for the first case when teaching C++, ...
      (alt.comp.lang.learn.c-cpp)