Почему запись во временный поток не удалась? - PullRequest
7 голосов
/ 03 марта 2011

Рассмотрим следующий код:

#include <sstream>
#include <iostream>

class Foo : public std::stringstream {
public:
    ~Foo() { std::cout << str(); }
};

int main()
{
    Foo foo;
    foo << "Test1" << std::endl;

    Foo() << "Test2" << std::endl;

    return 0;
}

Когда я выполняю это, это дает мне:

004177FC
Test1

Я не понимаю, почему второй пример дает мне бред. Временное должно жить до тех пор, пока не будет вычислено все выражение, так почему же оно не ведет себя так же, как в первом примере?

1 Ответ

7 голосов
/ 03 марта 2011

Я проверял это.

Я могу догадаться, что operator<< не может связать временную ссылку с неконстантной ссылкой, поэтому любые внешне определенные функции оператора << не будут работать с временной переменной Foo, но любые члены класса будут работать, если <code>ostream или ostringstream имеет внутренних operator<< членов, с которыми они будут работать.

Следовательно, может быть, перегрузка указателя является функцией-членом, тогда как специальная для const char * объявлена ​​извне.

Невременный может связываться с неконстантной ссылкой для более специализированной перегрузки.

Если вам это действительно нужно, вы можете обойти это с помощью оболочки

class Foo :
{
    mutable std::ostringstream oss;
public:
  ~Foo()
  {
    std::cout << oss.str();
  }

  template<typename T>
  std::ostream&
  operator<<( const T& t ) const
  {
      return oss << t;
  }
};

Проверено и работает. Первый оператор << вернет вам базовый поток. </p>

Я тоже это пробовал, но это вывело:

class Foo : std::ostringstream
{
    Foo & nonconstref;
public:
   Foo() : nonconstref( *this ) {}
  ~Foo()
  {
    std::cout << str();
  }

  template<typename T>
  std::ostream&
  operator<<( const T& t ) const
  {
      return nonconstref << t;
  }
};

Это также работает:

class Foo : public std::ostringstream
{
public:
   Foo()  {}
  ~Foo()
  {
    std::cout << str();
  }

  Foo& ncref()
  {
       return *this;
  }
};

int main()
{
    Foo foo;
    foo << "Test1" << std::endl;

    Foo().ncref() << "Test2" << std::endl;

}
...