2013-04-21 28 views
2

我試圖從頭開始構建一些簡單的日誌記錄功能,像'< <'這樣的接口,並且遇到了一些編譯器問題。這裏是我的代碼的基礎:複製構造錯誤,沒有明顯的副本

#include <string.h> 
#include <sstream> 
#include <iostream> 

class Logger 
{ 
public: 
    class Buffer 
    { 
    public: 
     Buffer(Logger &parent) : mPar(parent) 
     { 
     } 

     ~Buffer(void) 
     { 
      mPar.endline(os); 
     } 

     template<class T> 
     Buffer& operator<<(const T& x) 
     { 
      os << x; 
      return *this; 
     } 

     Logger& mPar; 
     std::ostringstream os; 
    }; 

    Buffer write(void) 
    { 
     return Buffer(*this); 
    } 

    void endline(std::ostringstream& os) 
    { 
     std::cout << os.str() << std::endl; 
    } 
}; 

int main(int argc, char **argv) 
{ 
    Logger log; 

    log.write() << "fred" << 3 << "bob"; 
} 

我得到的錯誤是:

In file included from /usr/include/c++/4.6/ios:45:0, 
       from /usr/include/c++/4.6/istream:40, 
       from /usr/include/c++/4.6/sstream:39, 
       from test.cpp:2: 
/usr/include/c++/4.6/bits/ios_base.h: In copy constructor ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’: 
/usr/include/c++/4.6/bits/ios_base.h:788:5: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private 
/usr/include/c++/4.6/bits/basic_ios.h:64:11: error: within this context 
In file included from test.cpp:2:0: 
/usr/include/c++/4.6/sstream: In copy constructor ‘std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)’: 
/usr/include/c++/4.6/sstream:373:11: note: synthesized method ‘std::basic_ios<char>::basic_ios(const std::basic_ios<char>&)’ first required here 
/usr/include/c++/4.6/streambuf: In copy constructor ‘std::basic_stringbuf<char>::basic_stringbuf(const std::basic_stringbuf<char>&)’: 
/usr/include/c++/4.6/streambuf:782:7: error: ‘std::basic_streambuf<_CharT, _Traits>::basic_streambuf(const __streambuf_type&) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_streambuf<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>]’ is private 
/usr/include/c++/4.6/sstream:60:11: error: within this context 
/usr/include/c++/4.6/sstream: In copy constructor ‘std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)’: 
/usr/include/c++/4.6/sstream:373:11: note: synthesized method ‘std::basic_stringbuf<char>::basic_stringbuf(const std::basic_stringbuf<char>&)’ first required here 
test.cpp: In copy constructor ‘Logger::Buffer::Buffer(const Logger::Buffer&)’: 
test.cpp:8:8: note: synthesized method ‘std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)’ first required here 
test.cpp: In member function ‘Logger::Buffer Logger::write()’: 
test.cpp:33:22: note: synthesized method ‘Logger::Buffer::Buffer(const Logger::Buffer&)’ first required here 

從我已經能夠到目前爲止發現的錯誤,因爲你不能在ostringstream上調用複製構造函數。據我所知,我沒有直接調用拷貝構造函數,也沒有拷貝Buffer,只是在'return'語句中構造它。

另一個有趣的事情是,這個代碼在Visual Studio 2010下很好地編譯,在將它集成到我的應用程序(它使用GCC 4.6.3編譯)之前,它將它敲掉。

我是否正確解釋了問題,如果是的話 - 隱式副本在哪裏,以及如何消除它?

回答

6

第一個問題是std::ostringstream is non-copyable,並且您在創建副本Buffer時嘗試創建副本。

爲什麼要在這個return聲明創建的Buffer副本原因:

return Buffer(*this); 

那是你Buffer類沒有一個隱含產生的移動構造函數。而它沒有的原因是Buffer有一個用戶定義的析構函數,它禁止移動構造函數的隱式生成。

您可以定義一個明確的:

Buffer(Buffer&& b) 
     : 
     mPar(b.mPar), 
     os(std::move(b.os)) 
    { 
    } 

但是你應該知道的事實標準庫的一些實施不完全兼容,並沒有實現move constructor of std::ostringstream

+0

爲什麼你不'std :: move''b.mPar'? – 2013-04-21 13:50:04

+0

@MemyselfandI:'mPar'是一個左值引用。 'std :: move'返回一個右值引用。您不能然後分配左值引用的右值引用 – 2013-04-21 13:52:37

+0

因此,當你說* lvalue-reference *你的意思是**不是**一個xvalue,只是一個常規變量? – 2013-04-21 14:07:00

相關問題