while循环中的智能指针测试:使用逗号运算符?

时间:2013-02-22 10:33:33

标签: c++ loops smart-pointers comma-operator

我最近看到这样的代码:

// 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
}

......不会让我感到非常理想......

5 个答案:

答案 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
}