You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用>>操作符的折叠表达式问题:为何std::cin读取参数包失败?

问题根源其实很明确,主要是这两点!

嘿,这个问题我刚学折叠表达式的时候也踩过坑!核心问题出在**std::cin的输入操作符要求左值引用**,而你的参数包传递方式不对,另外顺便给你捋清楚折叠表达式的展开逻辑,避免后续踩其他坑。

1. 最致命的错误:参数没传引用,cin读进了临时副本里

先看你能正常运行的writeall,它的逻辑是没问题的——std::cout <<只需要读取参数的值,不管是传值还是传引用都能工作,甚至字面量(比如你传的1、2、3、4)也能直接用,因为operator<<有对应的重载接受右值。

但std::cin >>完全是另一回事:它的作用是把输入的值写入到你传入的变量里,所以operator>>的第二个参数必须是非const的左值引用(签名大概是std::istream& operator>>(std::istream&, T&))。如果你的readall函数是这样写的:

template<typename... Args>
void readall(Args... args) { // 传值!错误!
    (std::cin >> ... >> args);
}

那这里的args都是你传入变量的临时副本,cin把值读到这些副本里之后,副本就销毁了,原变量根本没变化;要是遇到不能拷贝的类型,编译直接就报错。你说的“异常”大概率就是因为原变量没被修改,或者读取失败导致的奇怪行为。

把参数改成左值引用就解决了:

template<typename... Args>
void readall(Args&... args) { // 传左值引用!正确!
    (std::cin >> ... >> args);
}

这样cin就能直接修改你传入的原变量,读取逻辑就正常了。

2. 折叠表达式的展开顺序是对的,这点不用慌

你用的(std::cin >> ... >> args)是C++17里的带初始值的左折叠,展开后的代码和你手动写的链式读取完全一致:

((std::cin >> arg1) >> arg2) >> arg3 >> arg4;

也就是按参数包的顺序依次读取,和我们平时写cin >> a >> b >> c的逻辑一样,这部分是没问题的。要是你写成右折叠(args >> ... >> std::cin),那顺序就会完全颠倒,那才会出问题,但你当前的写法是对的。

额外小提示:别忘了检查cin的读取状态

就算传对了引用,要是输入不符合预期(比如输入字符串给int变量),cin会设置failbit,后续的读取都会失效。可以把readall改成返回bool类型,方便调用方判断读取是否成功:

template<typename... Args>
bool readall(Args&... args) {
    return static_cast<bool>(std::cin >> ... >> args);
}

这样调用的时候就能知道读取有没有出错啦。

内容的提问来源于stack exchange,提问作者Matteo Monti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:44:43