Ultimate Efficiency

Discussion in 'C++' started by JKop, Jun 21, 2004.

  1. JKop

    JKop Guest

    Your program begins at:

    int main(void);


    Now, in main, you want to call a function. This particular function you want
    to call defines a local object of type Taste, and then returns this local
    object by value.

    In main, having called this function, what you want to do is bind a
    reference to the object returned from Taste and then continue on and use it
    just as if it were defined in main as a local object.

    The first restriction here is that the Standard declares that you can bind
    the object returned from a function only to a *const* reference.

    Altogether, you want just 1 object to be created. No temporaries. No copies.


    But... in actual fact you're going to have 3 objects:

    1: The local variable defined in the function

    2: The temporary returned

    3: You'll have to create another object in main and copy the temporary so as
    to alleviate the constness.


    I wrote the following code a few mins ago and it compiles and runs grand.
    I've tried my best to make the code as non-tedious as possible to read, so
    please just give it a glance over:


    #include <iostream>

    class Taste
    {
    public:

    static unsigned char amount_ever;

    static unsigned char amount_currently;


    int mouth;

    unsigned char age;


    void Swallow(void)
    {
    mouth += 2;
    }

    Taste(void) : mouth(7), age(14)
    {
    ++amount_ever;
    ++amount_currently;
    }

    Taste(Taste& original)
    {
    mouth = original.mouth;
    age = original.age;

    ++amount_ever;
    ++amount_currently;
    }

    ~Taste(void)
    {
    --amount_currently;
    }
    };


    unsigned char Taste::amount_ever = 0;

    unsigned char Taste::amount_currently = 0;


    Taste Powder(void)
    {
    Taste cream;

    cream.age = 4;

    cream.Swallow();

    return cream;
    }


    int main(void)
    {
    const Taste& yacht = Powder();

    Taste& boat = const_cast<Taste&>(yacht);


    //Now we have what we wanted, a local variable in main.

    boat.age = 12;

    boat.Swallow();



    std::cout << "Amount ever: " << (int)Taste::amount_ever << std::endl
    << "Amount currently: " << (int)Taste::amount_currently
    << std::endl;

    std::system("PAUSE");

    }



    Now first thing's first:

    I'm going to presume that casting away that constness and editing the object
    is undefined behaviour.
    Can anyone come up with any argument as to why the hell you've to bind to a
    *const* reference in the first place?! I'll wait for an answer to this
    question before I decide for myself if casting away the constness is
    "moral".


    Moving on:

    With the above code, by casting away the constness, I was aiming for
    amount_ever == 2. To my delight, it came up 1!!
    Obviously, *my* compiler has not created a temporary, it has returned the
    actual local object defined in the function. Which leads me to...
    Why the hell is this "optimization" compiler behaviour, as opposed to
    "run-of-the-mill" compiler behaviour?!! Can anyone supply me with any
    arguments as to why a function should copy the local variable and then
    return the copy, as opposed to just returning the local variable itself?!


    Here's my thoughts:

    My objective is very clear. In my mind, I know and trully believe that I
    should be able to do what I want to do with just the 1 object, as opposed to
    3! Without regard to the Standard, I believe that C++ as an excellent
    programming language should be able to achieve this, that it should be "run-
    of-the-mill" compiler behaviour, as opposed to "optimization" compiler
    behaviour.

    -JKop
     
    JKop, Jun 21, 2004
    #1
    1. Advertising

  2. JKop wrote:

    > Your program begins at:
    >
    > int main(void);
    >
    >
    > Now, in main, you want to call a function. This particular function you want
    > to call defines a local object of type Taste, and then returns this local
    > object by value.
    >
    > In main, having called this function, what you want to do is bind a
    > reference to the object returned from Taste and then continue on and use it
    > just as if it were defined in main as a local object.
    >
    > The first restriction here is that the Standard declares that you can bind
    > the object returned from a function only to a *const* reference.
    >
    > Altogether, you want just 1 object to be created. No temporaries. No copies.
    >
    >
    > But... in actual fact you're going to have 3 objects:
    >
    > 1: The local variable defined in the function
    >
    > 2: The temporary returned
    >
    > 3: You'll have to create another object in main and copy the temporary so as
    > to alleviate the constness.




    Or you can pass your object from main by reference. Did you forget that?





    > Now first thing's first:
    >
    > I'm going to presume that casting away that constness and editing the object
    > is undefined behaviour.
    > Can anyone come up with any argument as to why the hell you've to bind to a
    > *const* reference in the first place?! I'll wait for an answer to this
    > question before I decide for myself if casting away the constness is
    > "moral".



    By casting away the constness, you use a non-const reference to a
    temporary which is going to be destroyed at the end of yacht scope. Also
    this kind of hackery means that the programmer doesn't know exactly what
    he wants to do.




    >
    >
    > Moving on:
    >
    > With the above code, by casting away the constness, I was aiming for
    > amount_ever == 2. To my delight, it came up 1!!
    > Obviously, *my* compiler has not created a temporary, it has returned the
    > actual local object defined in the function. Which leads me to...
    > Why the hell is this "optimization" compiler behaviour, as opposed to
    > "run-of-the-mill" compiler behaviour?!! Can anyone supply me with any
    > arguments as to why a function should copy the local variable and then
    > return the copy, as opposed to just returning the local variable itself?!



    Why did you expect it to be 2? The temporary should have the value 1 for
    both amount_ever ans amount_currently.


    The local variable is destroyed at the end of its scope. Anything else
    would be against C++ rules.



    >
    >
    > Here's my thoughts:
    >
    > My objective is very clear. In my mind, I know and trully believe that I
    > should be able to do what I want to do with just the 1 object, as opposed to
    > 3!



    My suggestion is to have a slow, thorough read of an up to date ISO C++
    book.



    > Without regard to the Standard, I believe that C++ as an excellent
    > programming language should be able to achieve this, that it should be "run-
    > of-the-mill" compiler behaviour, as opposed to "optimization" compiler
    > behaviour.


    :) If you have space/run-time efficiency concerns you should pass by
    reference (using pointers or references). It has nothing to do with C++
    but with the proper use of it.






    Regards,

    Ioannis Vranos
     
    Ioannis Vranos, Jun 21, 2004
    #2
    1. Advertising

  3. JKop

    JKop Guest

    Ioannis Vranos posted:

    > Or you can pass your object from main by reference. Did you forget
    > that?



    The function's already written. Look at it from that point of view.

    I think it's cleaner that the function itself should have the obligation of
    declaring the variable and giving it back. You have the choice to just let
    the returned object die, or prolong its life by binding it to a reference.


    > By casting away the constness, you use a non-const reference to a
    > temporary which is going to be destroyed at the end of yacht scope.



    Exactly my intention. boat and yacht have the same scope in anyway, so
    there's no problem there.


    > Why did you expect it to be 2? The temporary should have the value 1
    > for both amount_ever ans amount_currently.



    The temporary should?

    amount_ever and amount_currently are static

    Tasete::amount_ever

    I was expecting it to be 2 because my Powder function "should" have made a
    copy of its local object and then returned the copy, aka a temporary. This
    would bring the count to 2.


    > The local variable is destroyed at the end of its scope. Anything else
    > would be against C++ rules.



    First you said that amount_ever should be 1.
    Now you're saying that it would be against C++ rules to return the local
    object, indicating that the local variable should be copied to a temporary
    and the temporary be returned. This brings the count to 2.

    A) No temporary. Return local variable. amount_ever = 1

    B) Create temporay. Return temporary. amount_ever = 2


    -JKop
     
    JKop, Jun 21, 2004
    #3
  4. JKop

    Andre Kostur Guest

    JKop <> wrote in news:w8HBc.2807$:

    > Ioannis Vranos posted:
    >
    >> Or you can pass your object from main by reference. Did you forget
    >> that?

    >
    >
    > The function's already written. Look at it from that point of view.
    >
    > I think it's cleaner that the function itself should have the
    > obligation of declaring the variable and giving it back. You have the
    > choice to just let the returned object die, or prolong its life by
    > binding it to a reference.


    Or why not:

    Taste yacht(Powder());

    And let the Return Value Optimization deal with the extra copies of Taste
    which can be eliminated?
     
    Andre Kostur, Jun 21, 2004
    #4
  5. JKop wrote:

    > The function's already written. Look at it from that point of view.




    Then the library maker must have a slow, thorough read of an up to date
    ISO C++ book, as I have been doing myself too.


    Another alternative could be the function to create the object on the
    free store and return a pointer to it.

    In any case, what you have done is not used for objects having large
    space/time costs.



    > I think it's cleaner that the function itself should have the obligation of
    > declaring the variable and giving it back. You have the choice to just let
    > the returned object die, or prolong its life by binding it to a reference.



    All are a matter of logic. If you are expecting that the function has
    the obligation to create that type of object, then you should make it
    create it on the free store and return it back to the caller.



    > The temporary should?
    >
    > amount_ever and amount_currently are static
    >
    > Tasete::amount_ever
    >
    > I was expecting it to be 2 because my Powder function "should" have made a
    > copy of its local object and then returned the copy, aka a temporary. This
    > would bring the count to 2.




    Ok I got a head ache, let's use this simpler code for reference:


    #include <iostream>
    #include <cstdlib>

    class test
    {
    public:
    static int counter;

    test() { ++counter; }
    };

    int test::counter=0;


    test somefunc()
    {
    test a;

    return a;
    }



    int main()
    {
    using namespace std;

    somefunc();

    cout<<test::counter<<endl;

    system("pause");
    }


    G++ produces:

    C:\c>temp
    1
    Press any key to continue . . .


    MSVC++ produces:

    2
    Press any key to continue . . .



    Obviously G++ performs an optimisation and uses the same object instead
    of creating a temporary one. Strictly speaking it is a G++ bug, however
    probably its makers considered that this optimisation has not real-life
    implications.

    Strictly ISO C++ speaking, you can report it as a defect.



    > First you said that amount_ever should be 1.
    > Now you're saying that it would be against C++ rules to return the local
    > object, indicating that the local variable should be copied to a temporary
    > and the temporary be returned. This brings the count to 2.



    Yes, it should be 2. At the first time I was confused with your
    redundant counter usage.






    Regards,

    Ioannis Vranos
     
    Ioannis Vranos, Jun 21, 2004
    #5
  6. JKop

    JKop Guest

    > class test
    > {
    > public:
    > static int counter;
    >
    > test() { ++counter; }


    test(test& original)
    {
    ++counter;
    }

    //It's the copies we're woried about!

    > };
    >
    > int test::counter=0;
     
    JKop, Jun 22, 2004
    #6
  7. "Ioannis Vranos" <> wrote in message
    news:cb7hfo$dmo$...
    > Ok I got a head ache, let's use this simpler code for reference:
    >
    >
    > #include <iostream>
    > #include <cstdlib>
    >
    > class test
    > {
    > public:
    > static int counter;
    >
    > test() { ++counter; }


    you forgot
    test(const test&)
    {
    ++counter;
    }
    > };
    >
    > int test::counter=0;
    >
    >
    > test somefunc()
    > {
    > test a;
    >
    > return a;
    > }
    >
    >
    >
    > int main()
    > {
    > using namespace std;
    >
    > somefunc();
    >
    > cout<<test::counter<<endl;
    >
    > system("pause");
    > }
    >
    >
    > G++ produces:
    >
    > C:\c>temp
    > 1
    > Press any key to continue . . .
    >
    >
    > MSVC++ produces:
    >
    > 2
    > Press any key to continue . . .
    >

    I presume that you have copy constructor
    in compiled version.

    >
    >
    > Obviously G++ performs an optimisation and uses the same object instead
    > of creating a temporary one. Strictly speaking it is a G++ bug, however
    > probably its makers considered that this optimisation has not real-life
    > implications.
    >
    > Strictly ISO C++ speaking, you can report it as a defect.
    >


    I don't think so. Check out 12.18.15:

    "
    Whenever a temporary class object is copied using a copy constructor, and
    this object and the copy have the same cvunqualified
    type, an implementation is permitted to treat the original and the copy as
    two different ways of referring to the same object and not perform a copy at
    all, even if the class copy constructor or destructor have
    side effects. For a function with a class return type, if the expression in
    the return statement is the name of a local object, and the cvunqualified
    type of the local object is the same as the function
    return type, an implementation is permitted to omit creating the temporary
    object to hold the function return value, even if the class
    copy constructor or destructor has side effects. In these cases, the object
    is destroyed at the later of times when the original and the copy would have
    been destroyed without the optimization.

    111) [Example:

    class Thing {
    public:
    Thing();
    ~Thing();
    Thing(const Thing&);
    Thing operator=(const Thing&);
    void fun();
    };

    Thing f() {
    Thing t;
    return t;
    }

    Thing t2 = f();

    Here t does not need to be copied when returning from f. The return value of
    f may be constructed directly into the object t2. ]

    "

    Greetings, Bane.
     
    Branimir Maksimovic, Jun 22, 2004
    #7
  8. JKop

    JKop Guest

    Branimir Maksimovic posted:

    > I don't think so. Check out 12.18.15:
    >
    > "
    > Whenever a temporary class object is copied using a copy constructor,
    > and this object and the copy have the same cvunqualified
    > type, an implementation is permitted to treat the original and the copy
    > as two different ways of referring to the same object and not perform a
    > copy at all, even if the class copy constructor or destructor have
    > side effects. For a function with a class return type, if the
    > expression in
    > the return statement is the name of a local object, and the
    > cvunqualified type of the local object is the same as the function
    > return type, an implementation is permitted to omit creating the
    > temporary object to hold the function return value, even if the class
    > copy constructor or destructor has side effects. In these cases, the
    > object
    > is destroyed at the later of times when the original and the copy would
    > have been destroyed without the optimization.



    This pleases me.

    But... that doesn't address the issue of a temporary being made in the first
    place when one is not necesary! For example:

    int monkey(void)
    {
    return 22;
    }

    In the above, a temporary definitely is necessary.

    int monkey(void)
    {
    int cow = 22;

    return cow;
    }

    In the above, a temporary is unncecessary. It can simply just return cow.
    But does it...? And what does the Standard have to say about it?


    > 111) [Example:
    >
    > class Thing {
    > public:
    > Thing();
    > ~Thing();
    > Thing(const Thing&);
    > Thing operator=(const Thing&);
    > void fun();
    > };
    >
    > Thing f() {
    > Thing t;
    > return t;
    > }
    >
    > Thing t2 = f();
    >
    > Here t does not need to be copied when returning from f. The return
    > value of f may be constructed directly into the object t2. ]


    Just so you know, the operator= is never called in your code.


    -JKop
     
    JKop, Jun 22, 2004
    #8
  9. "JKop" <> wrote in message
    news:r5UBc.2844$...
    >
    > But... that doesn't address the issue of a temporary being made in the

    first
    > place when one is not necesary! For example:
    >
    > int monkey(void)
    > {
    > return 22;
    > }
    >
    > In the above, a temporary definitely is necessary.


    What temporary? As I understand when talking about
    temporaries we are thinking about instances of
    structs/classes with constructors.
    Above can be compiled with just two assembly
    instructions:
    move 22 to register and return from function.

    >
    > int monkey(void)
    > {
    > int cow = 22;
    >
    > return cow;
    > }
    >
    > In the above, a temporary is unncecessary.

    There is no temporary in this case either.
    It can be compiled with just two assembly
    instructions as previous example.

    > It can simply just return cow.
    > But does it...?
    > And what does the Standard have to say about it?


    "
    [basic.stc.auto] 3.7.2 Automatic storage duration

    1 Local objects explicitly declared auto or register or not explicitly
    declared static or extern have automatic storage duration. The storage for
    these objects lasts until the block in which they are created exits.

    2 [Note: these objects are initialized and destroyed as described in 6.7. ]

    3 If a named automatic object has initialization or a destructor with side
    effects, it shall not be destroyed before the end of its block, nor shall it
    be eliminated as an optimization even if it appears to be unused, except
    that a class object or its copy may be eliminated as specified in 12.8.

    "

    It is clear that return value optimization only refers to
    classes/structs with constructors/destructors

    >
    >
    > > 111) [Example:
    > >
    > > class Thing {
    > > public:
    > > Thing();
    > > ~Thing();
    > > Thing(const Thing&);
    > > Thing operator=(const Thing&);
    > > void fun();
    > > };
    > >
    > > Thing f() {
    > > Thing t;
    > > return t;
    > > }
    > >
    > > Thing t2 = f();
    > >
    > > Here t does not need to be copied when returning from f. The return
    > > value of f may be constructed directly into the object t2. ]

    >
    > Just so you know, the operator= is never called in your code.


    This is just one of two forms of initialization.

    "

    The initialization that occurs in argument passing, function return,
    throwing an exception (15.1), handling an exception (15.3), and
    braceenclosed initializer lists (8.5.1) is called copyinitialization
    and is equivalent to the form

    T x = a;

    The initialization that occurs in new expressions (5.3.4), static_cast
    expressions (5.2.9), functional notation type conversions (5.2.3), and base
    and member initializers (12.6.2) is called directinitialization
    and is equivalent to the form

    T x(a);

    "


    Greetings, Bane.
     
    Branimir Maksimovic, Jun 22, 2004
    #9
  10. "JKop" <> wrote in message
    news:r5UBc.2844$...
    > Branimir Maksimovic posted:
    >
    >
    > int monkey(void)
    > {
    > int cow = 22;
    >
    > return cow;
    > }
    >
    > In the above, a temporary is unncecessary. It can simply just return cow.


    Ah, think I know what you mean by temporary.

    const int& tmpref = monkey();

    in this case termorary variable must be created in order to
    initialize reference with it.

    int notemp = monkey();

    in this case there is no temporary variable created.

    Greetings, Bane.
     
    Branimir Maksimovic, Jun 22, 2004
    #10
  11. JKop wrote:

    > //It's the copies we're woried about!




    Actually I copied and pasted the wrong code but with the right results.
    The correct one:


    #include <iostream>
    #include <cstdlib>

    class test
    {
    public:
    static int counter;

    test() { ++counter; }
    test(const test &x) { ++counter; }
    };

    int test::counter=0;


    test somefunc()
    {
    test a;

    return a;
    }



    int main()
    {
    using namespace std;

    const test&r=somefunc();

    cout<<test::counter<<endl;

    system("pause");
    }



    It produces 2 with MSVC++ and 1 with G++.






    Regards,

    Ioannis Vranos
     
    Ioannis Vranos, Jun 22, 2004
    #11
  12. Branimir Maksimovic wrote:


    > I don't think so. Check out 12.18.15:



    12.8.15. It took few time to track it down.



    >
    > "
    > Whenever a temporary class object is copied using a copy constructor, and
    > this object and the copy have the same cvunqualified
    > type, an implementation is permitted to treat the original and the copy as
    > two different ways of referring to the same object and not perform a copy at
    > all, even if the class copy constructor or destructor have
    > side effects. For a function with a class return type, if the expression in
    > the return statement is the name of a local object, and the cvunqualified
    > type of the local object is the same as the function
    > return type, an implementation is permitted to omit creating the temporary
    > object to hold the function return value, even if the class
    > copy constructor or destructor has side effects. In these cases, the object
    > is destroyed at the later of times when the original and the copy would have
    > been destroyed without the optimization.




    Well, there is always something new to learn. Thanks for the
    information. :)






    Regards,

    Ioannis Vranos
     
    Ioannis Vranos, Jun 22, 2004
    #12
  13. Branimir Maksimovic wrote:

    > This is just one of two forms of initialization.
    >
    > "
    >
    > The initialization that occurs in argument passing, function return,
    > throwing an exception (15.1), handling an exception (15.3), and
    > braceenclosed initializer lists (8.5.1) is called copyinitialization
    > and is equivalent to the form
    >
    > T x = a;
    >
    > The initialization that occurs in new expressions (5.3.4), static_cast
    > expressions (5.2.9), functional notation type conversions (5.2.3), and base
    > and member initializers (12.6.2) is called directinitialization
    > and is equivalent to the form
    >
    > T x(a);
    >
    > "




    Doesn't the above mean that the temporary returned from a function call
    is created using operator=() instead of copy constructor?!


    However as far as I know(?) the copy constructor is used in this case.






    Regards,

    Ioannis Vranos
     
    Ioannis Vranos, Jun 22, 2004
    #13
  14. Ioannis Vranos wrote:
    >
    > Branimir Maksimovic wrote:
    >
    > > This is just one of two forms of initialization.
    > >
    > > "
    > >
    > > The initialization that occurs in argument passing, function return,
    > > throwing an exception (15.1), handling an exception (15.3), and
    > > braceenclosed initializer lists (8.5.1) is called copyinitialization
    > > and is equivalent to the form
    > >
    > > T x = a;
    > >
    > > The initialization that occurs in new expressions (5.3.4), static_cast
    > > expressions (5.2.9), functional notation type conversions (5.2.3), and base
    > > and member initializers (12.6.2) is called directinitialization
    > > and is equivalent to the form
    > >
    > > T x(a);
    > >
    > > "

    >
    > Doesn't the above mean that the temporary returned from a function call
    > is created using operator=() instead of copy constructor?!


    No.

    >
    > However as far as I know(?) the copy constructor is used in this case.


    Right. (Object creation is always handled through some constructor. operator=
    would need an already existing object, which is not there when the object
    gets born)

    In

    T x = a

    no operator= is involved. It is equivalent to

    T x( T(a) );

    First create a temporary from 'a' by taking a constructor which
    takes an 'a', then use that temporary in a copy constructor to
    create the final object.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, Jun 22, 2004
    #14
  15. "Ioannis Vranos" <> wrote in message
    news:...
    > Branimir Maksimovic wrote:
    >
    > > This is just one of two forms of initialization.
    > >
    > > "
    > >
    > > The initialization that occurs in argument passing, function return,
    > > throwing an exception (15.1), handling an exception (15.3), and
    > > braceenclosed initializer lists (8.5.1) is called copyinitialization
    > > and is equivalent to the form
    > >
    > > T x = a;
    > >
    > > The initialization that occurs in new expressions (5.3.4), static_cast
    > > expressions (5.2.9), functional notation type conversions (5.2.3), and

    base
    > > and member initializers (12.6.2) is called directinitialization
    > > and is equivalent to the form
    > >
    > > T x(a);
    > >
    > > "

    >
    >
    >
    > Doesn't the above mean that the temporary returned from a function call
    > is created using operator=() instead of copy constructor?!


    No. It is initialization of object, not assignment.

    T x(a); <=> T x = a;

    >
    >
    > However as far as I know(?) the copy constructor is used in this case.


    Yes, but not always.

    T func()
    {
    T tmp;
    //...
    return tmp;
    }

    If tmp is optimised out (RVO),
    return value temporary is constructed with default constructor
    so copy constructor is never called.

    Greetings, Bane.
     
    Branimir Maksimovic, Jun 22, 2004
    #15
  16. "Branimir Maksimovic" <> wrote in message
    news:cb9c3u$8dn$...
    >
    > T x(a); <=> T x = a;


    In case that typeof a is T
     
    Branimir Maksimovic, Jun 22, 2004
    #16
  17. JKop

    JKop Guest

    Branimir Maksimovic posted:

    >
    > "JKop" <> wrote in message
    > news:r5UBc.2844$...
    >> Branimir Maksimovic posted:
    >>
    >>
    >> int monkey(void)
    >> {
    >> int cow = 22;
    >>
    >> return cow;
    >> }
    >>
    >> In the above, a temporary is unncecessary. It can simply just return
    >> cow.

    >
    > Ah, think I know what you mean by temporary.
    >
    > const int& tmpref = monkey();
    >
    > in this case termorary variable must be created in order to
    > initialize reference with it.
    >
    > int notemp = monkey();
    >
    > in this case there is no temporary variable created.


    Nope, it's not the calling function that's creating the temporary, but the
    *called* function.

    -JKop
     
    JKop, Jun 22, 2004
    #17
  18. "JKop" <> wrote in message
    news:8oZBc.2883$...
    > Branimir Maksimovic posted:
    >
    > >
    > > "JKop" <> wrote in message
    > > news:r5UBc.2844$...
    > >> Branimir Maksimovic posted:
    > >>
    > >>
    > >> int monkey(void)
    > >> {
    > >> int cow = 22;
    > >>
    > >> return cow;
    > >> }
    > >>
    > >> In the above, a temporary is unncecessary. It can simply just return
    > >> cow.

    > >
    > > Ah, think I know what you mean by temporary.
    > >
    > > const int& tmpref = monkey();
    > >
    > > in this case termorary variable must be created in order to
    > > initialize reference with it.
    > >
    > > int notemp = monkey();
    > >
    > > in this case there is no temporary variable created.

    >
    > Nope, it's not the calling function that's creating the temporary, but the
    > *called* function.


    Just check out assembly code created from compiler.
    How and where do you think temporary variable is created in
    called function?

    Greetings, Bane.
     
    Branimir Maksimovic, Jun 22, 2004
    #18
  19. JKop wrote:

    > //It's the copies we're woried about!




    Today there was a much with my Usenet server and I do not know how much
    of my messages shown up, but to make sure that this one is shown, I am
    reposting it:



    Actually I copied and pasted the wrong code but with the right results.
    The correct one:


    #include <iostream>
    #include <cstdlib>

    class test
    {
    public:
    static int counter;

    test() { ++counter; }
    test(const test &x) { ++counter; }
    };

    int test::counter=0;


    test somefunc()
    {
    test a;

    return a;
    }



    int main()
    {
    using namespace std;

    const test&r=somefunc();

    cout<<test::counter<<endl;

    system("pause");
    }



    It produces 2 with MSVC++ and 1 with G++.






    Regards,

    Ioannis Vranos
     
    Ioannis Vranos, Jun 23, 2004
    #19
  20. JKop

    JKop Guest

    Branimir Maksimovic posted:

    > Just check out assembly code created from compiler.
    > How and where do you think temporary variable is created in
    > called function?



    I don't know assembly!


    -JKop
     
    JKop, Jun 23, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Koncept
    Replies:
    3
    Views:
    1,955
    Nick Santos
    Dec 6, 2003
  2. =?Utf-8?B?TWFyY28gQWx2ZXM=?=

    eCompany!!! The ultimate idea for the software development!!!

    =?Utf-8?B?TWFyY28gQWx2ZXM=?=, Aug 13, 2004, in forum: ASP .Net
    Replies:
    6
    Views:
    326
    M. Posseth
    Aug 21, 2004
  3. Andoni

    [OT] Ultimate Interface.

    Andoni, Sep 30, 2004, in forum: Java
    Replies:
    4
    Views:
    304
    ~misfit~
    Sep 30, 2004
  4. SivaSankar.Battula

    what is the ultimate difference?

    SivaSankar.Battula, Aug 27, 2005, in forum: Java
    Replies:
    6
    Views:
    387
    Thomas G. Marshall
    Aug 29, 2005
  5. Steve Horrillo
    Replies:
    3
    Views:
    431
    Roy Schestowitz
    Jun 28, 2005
Loading...

Share This Page