C ++ std :: queue不想push()

时间:2011-05-23 07:52:29

标签: c++

这是一个简单的类和简单的测试函数:

#include <queue>
#include <string>

namespace {
    using namespace std;
}

class NameStream {
    queue<string> stream;

public:
    string operator * () { return stream.front(); }
    NameStream &operator ++(int) { stream.pop(); return *this; }
    NameStream &operator ++() { stream.pop(); return *this; }
    NameStream &operator <<(string name) { stream.push(name); }

    operator bool() { return !stream.empty(); }
};

inline void nameStreamTest() {
    NameStream &stream = *new NameStream;

    stream << "hi" << "hey" << "hoy";

    while (stream) {
        printf("%s\n", (*stream++).c_str());
    }
}

它属于

NameStream &operator <<(string name) { stream.push(name); }

在队列的推送过程中,这是我的代码之外的堆栈:

#0  0x000b5079 in std::deque<std::string, std::allocator<std::string> >::push_back at stl_deque.h:1055
#1  0x000b50f2 in std::queue<std::string, std::deque<std::string, std::allocator<std::string> > >::push at stl_queue.h:204
#2  0x000b511c in NameStream::operator<< at NameStream.h:24
#3  0x000b520f in nameStreamTest at NameStream.h:32

我的经历在这种情况下失败了。我做错了什么?

P.S:

NameStream &stream = *new NameStream;

用于清除

的位置
stream

对象在地址(偏移?)0x7d(!)导致相同的异常。

4 个答案:

答案 0 :(得分:6)

在函数末尾添加一个return语句。

NameStream &operator <<(string name) { stream.push(name); return *this; }

添加:不返回有效的引用/值(如果需要)将导致UB,这将导致隐藏的崩溃或通常难以调试的错误行为(如您的情况)。因此,如果生成任何编译器警告,请永远不要忽略它。

答案 1 :(得分:2)

由于后缀运算符++的优先级高于运算符*,因此失败,所以当执行循环的最后一次迭代时,首先从队列pop开始,然后尝试执行front队列为空的时间。要解决这个问题,最简单的方法是将其分为两个语句:

while (stream) {
        printf("%s\n", (*stream).c_str());
        stream++;
    }

答案 2 :(得分:0)

它属于

NameStream &operator <<(string name) { stream.push(name); } 

您不会通过链接*this调用返回operator<<() ...,第二个和第三个调用没有有效的对象地址可供使用。

答案 3 :(得分:0)

您在代码中遇到了许多问题。

  1. operator<<中缺少返回(正如iammilind和其他人所指出的那样)导致您观察到的运行时错误。它可以纠正如下:

    NameStream &operator <<(string name) { stream.push(name); return *this; }
    
  2. 另一个问题是由于你的while循环体中的调用顺序是:

    1. operator ++(int)
    2. operator *()
    3. 因此,在最后一次迭代中,您首先在pop()operator++(int)然后尝试在空front()中调用operator*(),这将导致运行时错误。

      解决问题的最简单方法是重写while循环,如下所示。

      while (stream) {
        printf("%s\n", (*stream).c_str());
        ++stream;
      }
      
    4. 内存泄漏。您使用new调用分配NameStream对象,但从不调用delete。一个简单的解决方案是在堆栈上分配您的流对象:

      NameStream stream;