temporary object and const reference

Discussion in 'C++' started by zade, Nov 15, 2012.

  1. zade

    zade Guest

    codes like below:
    // [[code begin]]
    class Foo{
    public:
    int i;
    Foo& operator=(const Foo&){
    return *this;
    }
    };

    void func(Foo&){
    }

    void test(){
    func(Foo() = Foo()); // compile ok
    func(Foo()); // compile error
    }
    // [[code end]]


    Foo() generate a temporary object, which is a const reference object in c++. so why func(Foo() = Foo()) compile ok but func(Foo()) compile error.
     
    zade, Nov 15, 2012
    #1
    1. Advertising

  2. I

    On Thursday, November 15, 2012 8:42:05 AM UTC+3:30, zade wrote:
    > codes like below:
    >
    > // [[code begin]]
    >
    > class Foo{
    >
    > public:
    >
    > int i;
    >
    > Foo& operator=(const Foo&){
    >
    > return *this;
    >
    > }
    >
    > };
    >
    >
    >
    > void func(Foo&){
    >
    > }
    >
    >
    >
    > void test(){
    >
    > func(Foo() = Foo()); // compile ok
    >
    > func(Foo()); // compile error
    >
    > }
    >
    > // [[code end]]
    >
    >
    >
    >
    >
    > Foo() generate a temporary object, which is a const reference object in c++. so why func(Foo() = Foo()) compile ok but func(Foo()) compile error.


    I compiled and ran your program under Visual Studio 2010.
    There is no error message.

    Regards,
    -- Saeed Amrollahi Boyouki
     
    Saeed Amrollahi, Nov 15, 2012
    #2
    1. Advertising

  3. zade

    zade Guest

    在 2012å¹´11月15日星期四UTC+8下åˆ2æ—¶09分35秒,Saeed Amrollahi写é“:
    > I
    >
    >
    >
    > On Thursday, November 15, 2012 8:42:05 AM UTC+3:30, zade wrote:
    >
    > > codes like below:

    >
    > >

    >
    > > // [[code begin]]

    >
    > >

    >
    > > class Foo{

    >
    > >

    >
    > > public:

    >
    > >

    >
    > > int i;

    >
    > >

    >
    > > Foo& operator=(const Foo&){

    >
    > >

    >
    > > return *this;

    >
    > >

    >
    > > }

    >
    > >

    >
    > > };

    >
    > >

    >
    > >

    >
    > >

    >
    > > void func(Foo&){

    >
    > >

    >
    > > }

    >
    > >

    >
    > >

    >
    > >

    >
    > > void test(){

    >
    > >

    >
    > > func(Foo() = Foo()); // compile ok

    >
    > >

    >
    > > func(Foo()); // compile error

    >
    > >

    >
    > > }

    >
    > >

    >
    > > // [[code end]]

    >
    > >

    >
    > >

    >
    > >

    >
    > >

    >
    > >

    >
    > > Foo() generate a temporary object, which is a const reference object inc++. so why func(Foo() = Foo()) compile ok but func(Foo()) compile error.

    >
    >
    >
    > I compiled and ran your program under Visual Studio 2010.
    >
    > There is no error message.
    >
    >
    >
    > Regards,
    >
    > -- Saeed Amrollahi Boyouki


    I use GCC 3.4.5
     
    zade, Nov 15, 2012
    #3
  4. zade

    Clinton Mead Guest

    On Thursday, November 15, 2012 4:12:05 PM UTC+11, zade wrote:
    > codes like below:
    >
    > // [[code begin]]
    >
    > class Foo{
    >
    > public:
    >
    > int i;
    >
    > Foo& operator=(const Foo&){
    >
    > return *this;
    >
    > }
    >
    > };
    >
    >
    >
    > void func(Foo&){
    >
    > }
    >
    >
    >
    > void test(){
    >
    > func(Foo() = Foo()); // compile ok
    >
    > func(Foo()); // compile error
    >
    > }
    >
    > // [[code end]]
    >
    >
    >
    >
    >
    > Foo() generate a temporary object, which is a const reference object in c++. so why func(Foo() = Foo()) compile ok but func(Foo()) compile error.


    func takes a non-const reference, not a const reference. '=' returns a non-const reference, so you can pass it to func, which takes a non-const reference, but Foo() doesn't return a non-const reference, it's a temporary, which you can only pass to a const reference.

    If this seems a bit dodgy that you can pass a "temporary" just by setting it equal to something, then yes, it is. In C++11 you can avoid it by having a separate copy assignment operator for objects which are in the temporary state, but I don't think you can do such a thing in C++03.

    Clinton
     
    Clinton Mead, Nov 15, 2012
    #4
  5. zade

    red floyd Guest

    On 11/14/2012 10:09 PM, Saeed Amrollahi wrote:
    'redacted]
    >>
    >>
    >> Foo() generate a temporary object, which is a const reference object in c++.
    >> so why func(Foo() = Foo()) compile ok but func(Foo()) compile error.

    >
    > I compiled and ran your program under Visual Studio 2010.
    > There is no error message.
    >



    That's a VS2010 "extension". Compile with /Za, for strict ISO compliance,
    and you will get the error.
    By default, MS will allow an rvalue to bind to a non-const reference
    parameter, but this is prohibited by the Standard.
     
    red floyd, Nov 15, 2012
    #5
  6. zade

    SG Guest

    Am 15.11.2012 06:12, schrieb zade:
    > codes like below:


    struct Foo {};

    > void func(Foo&){
    > }
    >
    > void test(){
    > func(Foo() = Foo()); // compile ok
    > func(Foo()); // compile error
    > }
    >
    >
    > Foo() generate a temporary object, which is a const reference object in c++. so why func(Foo() = Foo()) compile ok but func(Foo()) compile error.


    A temporary object is not a "const reference object". What does that
    even mean, "const reference object"? A reference is not an object and an
    object is not a reference. Also, there is no "const" involved in Foo().
    An expression has a type and a value category. The expression

    Foo()

    is of type Foo and is an "rvalue". As such you may not bind it to a
    non-const lvalue reference. But you can work your way around that in
    different ways:

    struct Foo {
    Foo& lvalue() {return *this;}
    };

    void sink(Foo&);

    int main() {
    sink(Foo().lvalue());
    }

    So, it is not specific to the assignment operator. If you're not
    disabling this explicitly, non-static functions can be invoked on
    temporaries. This means, at some point the adress of the temporary
    object will be "bound" to a this pointer.

    C++11 offers a way to turn this off:

    struct Foo {
    Foo& lvalue() & {return *this;}
    // ^
    // This is a ref qualifier
    };

    This makes the member function only applicable on non-const lvalue
    objects. (Note: I said "non-const lvalue object" because I don't know
    any better how to describe it. Of course, the lvalueness is not a
    property of the object but a property of the expression that refers to
    that object)

    Cheers!
    SG
     
    SG, Nov 15, 2012
    #6
    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. John Ky
    Replies:
    9
    Views:
    471
    John Ky
    Feb 23, 2004
  2. Dave Rahardja
    Replies:
    15
    Views:
    1,194
    Alf P. Steinbach
    Nov 3, 2005
  3. Javier
    Replies:
    2
    Views:
    627
    James Kanze
    Sep 4, 2007
  4. George2
    Replies:
    10
    Views:
    640
    Pete Becker
    Dec 17, 2007
  5. Replies:
    10
    Views:
    1,417
    James Kanze
    Nov 27, 2008
Loading...

Share This Page