向priority_queue<std::stringstream>推入元素时触发已删除构造函数错误如何解决?
解决std::priority_queue存储std::stringstream的编译错误
错误原因
你遇到的call to deleted constructor of 'std::basic_stringstream'错误,核心原因是std::stringstream的拷贝构造函数被显式删除。std::priority_queue在存储元素时需要执行拷贝(或移动)操作,直接存储stringstream对象会触发调用已删除的拷贝构造函数,导致编译失败。
能不能在优先队列中使用stringstream?
可以,但不能直接存储stringstream对象本身。有两种可行思路:要么改用存储格式化后的字符串(更贴合你的代码场景),要么用指针/智能指针间接存储stringstream。
修复方案
方案一:直接存储格式化后的字符串(推荐)
你的代码中,stringstream只是用来生成格式化字符串,后续操作仅依赖它的str()结果,完全没必要存储整个stream对象。这种方案最简洁高效:
- 修改
makeString函数,返回生成的字符串而非stringstream:
std::string makeString(std::string name, std::string number) { std::stringstream ss; if (number.size() == 1) { ss << "0" << number << " - " << name << std::endl; } else { ss << number << " - " << name << std::endl; } return ss.str(); }
- 将优先队列改为存储
std::string,并调整main中的逻辑:
int main(int argc, char const* argv[]) { std::string inputs; std::string priority; std::priority_queue<std::string> pqueue; while (true) { input("What do you want to do? ", inputs); if (inputs == "add") { input("Name: ", inputs); input("Priority: ", priority); std::string formatted_str = makeString(inputs, priority); std::cout << formatted_str; pqueue.push(formatted_str); } else if (inputs == "take") { std::cout << pqueue.top() << std::endl; pqueue.pop(); } else if (inputs == "end") { return 0; } else { std::cout << inputs << " isn't a valid operation" << std::endl; } } }
方案二:用智能指针间接存储stringstream(仅需保留stream状态时使用)
如果确实需要在队列中保留stringstream的可写入状态,可以使用std::unique_ptr(支持移动语义,无拷贝操作)来包装stringstream:
- 定义带自定义比较器的优先队列(默认按指针地址排序,不符合业务需求):
struct CompareStreamPtr { bool operator()(const std::unique_ptr<std::stringstream>& a, const std::unique_ptr<std::stringstream>& b) { // 此处逻辑决定优先级,示例为按字符串升序排列(大顶堆特性,a的字符串小于b时b优先出队) return a->str() < b->str(); } }; std::priority_queue< std::unique_ptr<std::stringstream>, std::vector<std::unique_ptr<std::stringstream>>, CompareStreamPtr > pqueue;
- 调整add和take逻辑:
if (inputs == "add") { input("Name: ", inputs); input("Priority: ", priority); auto ss = std::make_unique<std::stringstream>(); *ss << makeString(inputs, priority).str(); std::cout << ss->str(); pqueue.push(std::move(ss)); // 移动语义避免拷贝 } else if (inputs == "take") { auto& top_stream = pqueue.top(); std::cout << top_stream->str() << std::endl; pqueue.pop(); }
总结
- 优先选择方案一,它更贴合你的代码实际需求,代码简洁且性能更优。
- 仅当需要在队列中保留stringstream的可操作状态时,才考虑方案二。
内容的提问来源于stack exchange,提问作者Vincent Reiley
相关产品推荐
相关产品推荐

