Search

C++: member rvalue references are initialized with erroneous copies in constructor initializer list by to.g

Closed
as Fixed Help for as Fixed

1
0
Sign in
to vote
Type: Bug
ID: 681998
Opened: 7/29/2011 4:49:52 AM
Access Restriction: Public
Moderator Decision: Sent to Engineering Team for consideration
0
Workaround(s)
0
User(s) can reproduce this bug
Suppose we have a class with a member that holds an rvalue reference, and we want to initialize it in the initializer list of the constructor:

template< class A >
struct Foo {
    A&& a;
    Foo( A&& a_ ): a( std::forward<A>(a_) ) {}
};

If the type "A" is int, a local copy of the (referenced int of the) constructor argument "a_" is created and the reference "a" points to this local copy. However, the member "a" really should reference the original value that was referenced by a_.

This leads to problems if the address and lifetime of the reference is important.

Note that the local copy only seems to be created in the constructor's initializer list. For example, "A&& a(std::forward<A>(a_))" does not create a copy. There also seems to be no local copy if the type "A" is user defined (see below).
Details (expand)

Visual Studio/Team Foundation Server/.NET Framework Tooling version

Visual Studio 2010 SP1

Steps to reproduce

The following code implements a class template Foo that saves a reference to some value, and an operator<< for Foo that prints this value. Calling makeFoo(int(2)) creates a local copy of the temporary int in Foo::Foo() and initializes Foo::a to reference this copy. Of course, this local variable does not exist anymore during output of Foo, and "std::cout << makeFoo(int(2));" prints garbage.

If we avoid the constructor and initialize the (otherwise similar) class Bar directly in makeBar, everything works fine. Also, if we wrap the int with a custom struct, there is no local copy and all is fine. I cannot see what makes the difference here.

To reproduce, compile the following code with Debug settings:
----------------------------------------------------------------------------------

#include <iostream>


template< class A >
struct Foo {
    A&& a;
    Foo( A&& a_ ): a( std::forward<A>(a_) ) {} // triggers warning 4413: "reference member is initialized to a temporary that doesn't persist after the constructor exits"
    friend void operator<<(std::ostream& os, Foo<A> const& foo) { os << foo.a; }
};

template< class A >
Foo<A> makeFoo( A&& a ) {
    Foo<A> foo( std::forward<A>(a) );
    return foo;
}


template< class A >
struct Bar {
    A&& a;
    friend void operator<<(std::ostream& os, Bar<A> const& bar) { os << bar.a; }
};

template< class A >
Bar<A> makeBar( A&& a ) {
    Bar<A> bar={ std::forward<A>(a) };
    return bar;
}


struct Wrapper {
    int n;
    Wrapper() : n(0) {}
    friend void operator<<(std::ostream& os, Wrapper const& w) { os << w.n; }
};


int main(int argc, char* argv[]) {
    int n=1;
    std::cout << makeFoo(n); // works
    std::cout << makeFoo(int(2)); // broken
    std::cout << std::endl;

    std::cout << makeBar(n); // works
    std::cout << makeBar(int(2)); // works
    std::cout << std::endl;

    Wrapper w;
    std::cout << makeFoo(w); // works
    std::cout << makeFoo(Wrapper()); // works
    return 0;
}

Product Language

English

Operating System

Windows 7

Operating System Language

English

Actual results

13930488
12
00

-> NOTE: the first line really is random

Expected results

12
12
00
File Attachments
File Name Submitted By Submitted On File Size  
test3.cpp 7/29/2011 1 KB
Sign in to post a comment.
Posted by Microsoft on 8/13/2011 at 6:29 PM
Hi: this bug has been fixed and the fix will show up in a future release of Visual C++.

Thanks
Jonathan Caves
Visual C++ Compiler Team
Posted by MS-Moderator08 [Feedback Moderator] on 7/31/2011 at 7:50 PM
Thank you for submitting feedback on Visual Studio 2010 and .NET Framework. Your issue has been routed to the appropriate VS development team for investigation. We will contact you if we require any additional information.
Posted by MS-Moderator01 on 7/29/2011 at 5:50 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.