我最近看到这样的代码:
// 3rd Party API: (paraphrased)
void APIResetIterator(int ID); // reset iterator for call to next()
Mogrifier* APINext(int ID); // User must delete pointer returned
...
typedef std::unique_ptr<Mogrifier> MogPtr;
...
const it listID = 42;
APIResetIterator(listID);
MogPtr elem;
while (elem.reset(APINext(listID)), elem) {
// use elem
}
这是个好主意吗?它有效吗?
我将添加相应的for循环以便于参考:
for (MogPtr elem(APINext(listID)); elem; elem.reset(APINext(listID));) {
// use elem
}
......不会让我感到非常理想......
答案 0 :(得分:1)
它应该工作。有点棘手,不太明显,但其他方面的工作。也许使用for循环可以使代码更清晰。
答案 1 :(得分:1)
有用吗?好吧,它应该是,语法有效:指针重置为APINext()
返回的值,然后在NULL
条件下测试while
。
这是个好主意吗?这是一个品味问题,但很多人(包括我)不喜欢那种代码。它可能是合法的和有效的,但不是那么清楚,需要花时间去理解。对我来说,代码可读性非常重要,而且这个特殊的代码不是可读性的好例子。
答案 2 :(得分:1)
正如其他答案中所述:这在技术上是可行的并且按预期工作。但是你在质疑它实际上表明这不是一个好主意,因为它缺乏可读性。
这是一种伪装的for-loop,与此类似:
int i = -1;
while (++i, i<10) { something(i); }
换句话说,你可以通过实际使用for循环来使它更清晰:
for (MogPtr elem{APINext(listID)}; elem != nullptr; elem.reset(APINext(listID)))
{
// use elem
}
唯一的问题是你必须输入APINext
两次(震惊!),这可能就是为什么有人以现在的方式写它的原因。
获得的经验教训:可读性超过了懒惰。
编辑: imo选择APINext(listID)
两次实际上是一件好事,因为它清楚地表明它第一次实际上是初始化,其他时候,它是重新分配。
Edit2: {+ 1}}组合在C ++中看起来有点不寻常,因为C ++标准库迭代器可以处理运算符重载。在没有运算符重载的Java和其他语言中,这是正常的做事方式。如果需要,可以编写一个包含API调用的简单C ++样式转发迭代器:
Iterator/Next()
它不完整,我没有测试过它可能包含错误,但你得到了要点:)
答案 3 :(得分:0)
它确实有效,但它是否比for循环更好是另一个争论。在这种情况下,它避免了双重代码,因为获取第一个元素与获取下一个元素相同(APIResetIterator(listID);
除外)。所以这将是关于惯用编码(for循环)或避免双重代码(获取第一个元素并获得下一个元素)。
我的建议是在for循环中使用迭代器,但在这种情况下这可能不是那么好。
答案 4 :(得分:0)
也许我们应该把它写成:
template<class SPT, typename P>
SPT& reset(SPT& smartPtr, P ptr) {
smartPtr.reset(ptr);
return smartPtr;
}
for (MogPtr elem; reset(elem, APINext(listID));) {
// use elem
}