while循环中的智能指针测试:使用逗号运算符
Smart pointer test in a while loop: use the 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
}
我觉得也不是最理想的。。。
正如其他答案中所说:这在技术上是可以的,并且可以按预期工作。但你质疑它实际上表明这不是一个好主意,因为它缺乏可读性。
这有点像一个伪装的for循环,类似于这个:
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:Iterator/Next()
组合在C++中可能看起来有点不寻常,因为C++标准库迭代器使用运算符重载。在没有运算符重载的Java和其他语言中,这是正常的操作方式。如果你愿意,你可以编写一个简单的C++风格的前向迭代器包装API调用:
class MogrifierIterator {
MogPtr ptr_;
int listID_
public:
MogrifierIterator() : ptr_(nullptr) {} //end-Iterator
explicit MogrifierIterator(int listID) : ptr(nullptr), listID_(listID) {
APIResetIterator(listID_);
ptr_.reset(APINext(listID_));
}
Mogrifier& operator*() { return *ptr_; }
Mogrifier* operator->() { return ptr_.get(); }
MogrifierIterator& operator++() { ptr_.reset(APINext(listID_)); return *this; }
bool operator==(MogrifierIterator const& other)
{ return (ptr_==other.ptr_) && (ptr_ == nullptr || listID_ == other.listID_); }
};
//...
for (MogrifierIterator it(listID); it != Mogrifieriterator(); ++it)
{
it->mogrify();
}
它还不完整,我还没有测试过,它可能包含错误,但你会得到要点:)
它应该可以工作。这有点棘手,也不太明显,但在其他方面也能起到作用。也许使用for循环会使代码更清晰。
它能工作吗?应该,语法是有效的:指针重置为APINext()
返回的值,然后在while
条件下测试NULL
。
这是个好主意吗?这是一个品味问题,但很多人(包括我)不喜欢那种代码。这可能是合法和有效的,但并不那么清楚,需要一段时间才能理解。对我来说,代码的可读性非常重要,而这个特定的代码并不是可读性的好例子。
它确实有效,但它是否比for循环更好是另一个争论。在这种情况下,它避免了双重编码,因为获得第一个元素与获得下一个元素相同(除了APIResetIterator(listID);
)。因此,这将涉及惯用编码(针对循环)或避免双重编码(获取第一个元素和下一个元素)。
我的建议是在for循环中使用迭代器,但在这种情况下可能不太好。
也许我们应该把它写成:
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
}
- 如何使用重载的相等(==)运算符向测试用例添加描述
- 不能将重载比较运算符与 Catch 测试一起使用
- 如何测试成员相等运算符?
- std::is_invocable 用于测试任意方法是否存在的语法(不仅是运算符())
- 我在使用相等性测试布尔运算符时遇到问题
- 测试相等运算符
- STL 类型的 Google 测试和运算符<<重载
- Boost 的数据驱动测试的联接运算符"+"损坏了第一列
- 过载输入运算符未通过自动简单输入测试
- C++ XCode 中的错误:在定义运算符 * 时"no viable overloaded operator *=" *= 已经过测试并且正常运行
- 如何在输出运算符中测试std::showbase或std::noshowbase
- C++测试重载的+运算符
- VC++ Express 2010 在模板化类的重载赋值运算符的自赋值测试中出错
- 仅使用小于运算符测试等效性
- 如果运算符<对浮点类型正常工作,为什么我们不能将其用于相等性测试?
- 在测试已声明但未定义的运算符是否存在时,static_assert真的应该成功吗?
- 疑点在代码中测试赋值运算符的使用
- 如何测试字符串流运算符>>是否解析了错误类型并跳过它
- 默认复制赋值运算符未通过is_copy_assignable测试
- 我的测试.cpp文件使用的是默认运算符<<;这个签名有什么问题?