3
#include <iostream>
#include <string>
#include <memory>
#include <cstdlib>

std::string foo()
{
    return std::string("yyyyyyyyyyyyy");
}

void bar(std::string& s)
{
    std::cout << s << std::endl;
}


std::auto_ptr<std::string> foo1()
{
    bool x = std::rand() % 2;
    if (x) {
        return std::auto_ptr<std::string>(new std::string("eeeeeeeeeeee"));
    } else {
        return std::auto_ptr<std::string>(new std::string("aaaaaaaaaaaaa"));
    }
}


int main()
{
    //bar(foo());
    std::auto_ptr<std::string> a(foo1());    
}

The commented line: bar(foo()) doesn't compile because bar accepts non-const reference and foo returns rvalue. But the second line with std::auto_ptr compiles. Copy constructor of std::auto_ptr also accepts non-const reference. Why then it compiles? I used std::rand() in foo1 to eliminate RVO (Return value optimization).

Ashot
  • 10,807
  • 14
  • 66
  • 117

1 Answers1

2

This apparently works because of a little trick employed to release the internal pointer to the constructing std::auto_ptr. Case 4 from This Manual:

template< class Y >
auto_ptr( auto_ptr_ref<Y> m );

4) Constructs the auto_ptr with the pointer held in the auto_ptr instance referred to by m. p.release() is called for the auto_ptr p that m holds to acquire the ownership of the object. auto_ptr_ref is an implementation-defined type that holds a reference to auto_ptr. std::auto_ptr is implicitly convertible to and assignable from this type. The implementation is allowed to provide the template with a different name or implement equivalent functionality in other ways.

(emphasis added)

Galik
  • 47,303
  • 4
  • 80
  • 117