不能使用operator = with std :: stringstream

时间:2015-07-01 09:37:33

标签: c++ c++11 std stringstream

我正在尝试制作struct,其中一个成员属于std::stringstream类型。我正在使用C ++ 11,根据http://www.cplusplus.com/reference/sstream/stringstream/operator=/我可以做到。

这是我的代码:

struct logline_t
    {
        stringstream logString; /*!< String line to be saved to a file (and printed to cout). */
        ElogLevel logLevel; /*!< The \ref ElogLevel of this line. */
        timeval currentTime; /*!< time stamp of current log line */

        logline_t& operator =(const logline_t& a)
        {
            logString = a.logString;
            logLevel = a.logLevel;
            currentTime = a.currentTime;

            return *this;
        }
    };

它没有编译,因为我收到此错误:

error: use of deleted function ‘std::basic_stringstream<char>& std::basic_stringstream<char>::operator=(const std::basic_stringstream<char>&)’

我不明白为什么它不起作用。我也试过了logString = move(a.logString);。结果相同。我将非常感谢你的帮助。

编辑:这是我的代码,我已经应用了大多数用户建议的更改,并且在我的代码中他们没有编译。我在struct的最开始时仍然收到错误。

CLogger.h

第40行:../src/CLogger.h:40:9: error: use of deleted function ‘std::basic_stringstream<char>::basic_stringstream(const std::basic_stringstream<char>&)’

CLogger.cpp

第86行:../src/CLogger.cpp:86:41: error: use of deleted function ‘CLogger::logline_t::logline_t(const CLogger::logline_t&)’

第91行:../src/CLogger.cpp:91:9: error: use of deleted function ‘CLogger::logline_t::logline_t(const CLogger::logline_t&)’

如果需要任何其他信息,我将提供。

4 个答案:

答案 0 :(得分:12)

std::stringstream不可复制。要复制内容,您只需将一个流的内容写入另一个流:

logString << a.logString.str();

<强>更新: 此外,如果您没有遵循使用复制构造函数实现operator=复制和交换习惯用法的好建议,则必须首先清除该流:

logString.str({});
logString << a.logString.str();

或只是

logString.str(a.logString.str());

您也可能想要使用rdbuf()

logString << a.logString.rdbuf();

但这是不正确的,因为它改变了a.logString的状态(尽管a.logStringconsta.logString.rdbuf()是指向非const对象的指针)。以下代码演示了这一点:

logline_t l1;
l1.logString << "hello";
logline_t l2, l3;
l2 = l1;
l1.logString << "world";
l3 = l1;
// incorrectly outputs: l2: hello, l3: world
// correct output is: l2: hello, l3: helloworld
std::cout << "l2: " << l2.logString.str() << ", l3: " << l3.logString.str() << std::endl;

答案 1 :(得分:4)

Streams不可复制。但它们是可以移动的。

您仍然可以通过创建合适的stringstream来使您的副本分配操作符正常工作。

第三方面,将流作为成员感觉不太对劲?如果您真的想要这样做,为什么不使用ostringstream,为什么要stringstream?通过对此的反思,可以改进设计(并且可能会消除当前的问题)。

使用异常安全复制/交换习惯用法创建合适的stringstream(好,ostringstream)的解决方法示例:

#include <sstream>
#include <utility>          // std::swap

namespace my {
    using std::ostringstream;
    using std::swap;

    struct S
    {
        ostringstream line;

        void swap_with( S& other ) noexcept
        {
            swap( line, other.line );
        }

        auto operator=( S const& other )
            -> S&
        {
            S temp( other );
            swap_with( temp );
            return *this;
        }

        S() = default;

        S( S const& other )
            : line( other.line.str() )
        {}
    };
}  // namespace my

auto main() -> int
{
    my::S o1, o2;
    o1 = o2;
}

请注意,这取决于std::swap,它专门用于ostringstream

更简单但原则上不例外的安全解决方法的示例:

#include <sstream>
#include <utility>          // std::swap

namespace my {
    using std::ostringstream;
    using std::swap;

    struct S
    {
        ostringstream line;

        auto operator=( S const& other )
            -> S&
        {
            line.str( other.line.str() );   // This can in theory throw, but.
            return *this;
        }

        S() = default;

        S( S const& other )
            : line( other.line.str() )
        {}
    };
}  // namespace my

auto main() -> int
{
    my::S o1, o2;
    o1 = o2;
}

答案 2 :(得分:3)

原因:

SELECT * FROM table WHERE 'username' = 'MyEmail%40email.com' AND 'password' = '329670c3265b6ccd392e622733e9772f';通过移动分配其成员和基类来获取其右侧的内容。

在您重载的std::stringstream::operator=中,输入参数为operator=。因此,无法移动输入参数的成员const。此外,logString中的operator=(std::stringstream const&)已声明已删除。重载决策选择一个已删除的运算符,理所当然地,您将收到编译错误。

解决方案:

stringstream

Android Deleting Files MediaScannerConnection

答案 3 :(得分:1)

问题是您正在尝试复制不可复制std::stringstream对象。你可以通过不复制对象本身,但将其内容复制到新的std::stringstream

来解决这个问题

此外,您确实需要复制构造函数以及复制赋值运算符。在所谓的Rule Of Three中解释了提供这两者(通常也是析构函数)的需要。

此外,我们还需要添加默认的consructor ,因为添加复制构造函数会阻止编译器生成自己的默认构造函数

struct logline_t
{
    std::stringstream logString; /*!< String line to be saved to a file (and printed to cout). */
    ElogLevel logLevel; /*!< The \ref ElogLevel of this line. */
    timeval currentTime; /*!< time stamp of current log line */

    // default constructor needed because we made a copy constructor
    // which deleted the compiler generated default constructor!
    logline_t()
    : logLevel(0) // set suitable defaults
    {
        gettimeofday(&currentTime, 0); // for example
    }

    // copy constructor
    logline_t(const logline_t& ll)
    : logString(ll.logString.str()) // construct from contents .str()
    , logLevel(ll.logLevel)
    , currentTime(ll.currentTime)
    {
    }

    // copy assignment operator
    logline_t& operator=(const logline_t& a)
    {
        logString.str(a.logString.str()); // assign from contents
        logLevel = a.logLevel;
        currentTime = a.currentTime;

        return *this;
    }
};