for (const auto& dummy : input) {
cout << '.';
}
唯一的问题是,
dummy
是一个未使用的变量,我已经指示编译器禁止这些变量。我想到了两个不太优雅的解决方案,一个是在循环体中使用
(void)dummy;
来消除编译器警告,另一个则是使用传统的 for 循环,从 0 到 distance(begin(input), end(input))
。我试着省略变量名,但是编译失败了(并不让人意外)。
我正在使用 GCC 4.7.2。
for (const auto& dummy : input) {
cout << '.';
}
dummy
是一个未使用的变量,我已经指示编译器禁止这些变量。(void)dummy;
来消除编译器警告,另一个则是使用传统的 for 循环,从 0 到 distance(begin(input), end(input))
。use std::begin;
use std::end;
std::cout << std::string(std::distance(begin(input), end(input)), '.');
std::cout << std::string(input.size(), '.');
如果你想在循环中做一些更复杂的操作,只需使用 (void)dummy;
。这是清晰、众所周知和有效的。
同时,看看<algorithm>
;你正在实现的内容可能最好是用这些函数来实现。 C++调味是一个关于此的好演讲。
input.size()
太简单了? - rubenvbstd::distance
。但是这里被推断出我实际上想知道“如何编写一系列N个点”,这不是我所问的。对于在for循环内部编写更复杂的逻辑,我表示歉意。 - John Zwinck由于所有合理的建议都只是评论(现在有些属于已删除的答案),因此我将把它们汇总在这里。底线是:你根本不应该循环。
相反,使用容器的大小,然后按照需要执行相应次数的操作即可。以下是您提供的代码的建议变体:
cout << string(input.size(), '.'); // @Matt
std::fill_n(std::ostream_iterator<char>(std::cout), input.size(), '.'); // @Hilborn
同时仍然循环的代码(不推荐):
std::for_each(input.begin(), input.end(), [](type) { std::cout << '.'; }); // @Rapptz
std::transform(input.begin(), input.end(), std::ostream_iterator<char>(std::cout),
[] (auto&&) { return '.'; }); // @hilborn
std::for_each
是我原始问题中没有的最佳解决方案,我认为。 - John Zwinck如果您想执行的操作与您在示例中写的微不足道的操作相同,那么实现您想要的结果的更好方法是:
std::cout << std::string{boost::distance(input), '.'};
for_each
<algorithm>
正是您需要的。
Using boost:
#include <boost/range/algorithm.hpp>
boost::for_each(input, [](auto&& /*ignored*/) { /* do stuff */; });
Using the STL:
#include <algorithm>
std::for_each(std::begin(input), std::end(input), [](auto&& /*ignored*/) {
/* do stuff */;
});
break
或continue
,但是你可以提前使用return
来实现相同的行为。boost::distance()
。谢谢。 - John ZwinckSTL != stdlib
吗?在学习 C++ 时,我很困惑,因为人们在提到 stdlib
时使用了术语 STL
,而 std
命名空间就是 stdlib
。快速查看 for_each
何时添加到 stdlib
中,告诉我 STL
中从未有过任何 for_each
。https://dev59.com/UG435IYBdhLWcg3wyzaa#5205571; https://en.cppreference.com/w/cpp/algorithm/for_each - Andreas detests censorship<algorithm>
头文件是STL的一部分,而for_each
算法自C++标准化之前就已经成为其中的一部分(例如,请参阅SGI STL文档:http://www.martinbroadhurst.com/stl/for_each.html)。 - gnzlbgfor (const auto& dummy __attribute__((unused)) : input) {
cout << '.';
}
既然您已经在使用gcc,那么作为C++11属性,它应该写成(感谢Jonathan Wakely)
for (const auto& dummy [[gnu::unused]] : input) {
cout << '.';
}
cout << string(input.size(), '.')
非常不同。 - examplefor (const auto& dummy [[gnu::unused]] : input)
,它使用了供应商特定的属性,使用了gnu
属性命名空间。 - Jonathan Wakely好的,你可以使用#pragma来消除警告:
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wunused-variable"
/在此处插入代码/
#pragma GCC diagnostic pop
但我建议你不要这样做。考虑到权衡,"(void)dummy"选项更好。我也建议你不要像R Sahu建议的那样做一个虚拟的内联函数,因为这只会使你的代码变得混乱且复杂。
我认为在这种情况下,billz和moo-juice给出了很好的建议。你最好使用旧式的for循环。
我能想到一种情况,你可能想使用这里讨论的选项。如果容器"input"是一种需要遍历范围才能获取大小的类型,并且所讨论的代码将在性能关键区域中运行,你可能会发现优化掉两次循环的迭代是值得的。在这种情况下,请使用:
(void) dummy; // 消除不必要的警告。
然而,在你发布的示例代码中,几乎肯定不是这种情况,因为io操作将占主导地位,这是一种过早的优化。
请记住,您的代码将被阅读的次数比编写的次数多得多,因此请专注于使代码更易读。只有当使用新的C++功能可以增加代码的可读性、可维护性或灵活性——或者它带来了有意义的性能提升时,才会带来好处。
对于您发布的示例,您的指导原则应该是“对同事来说最容易阅读的是什么?”
另一种选择是调用一个虚拟的内联函数。
定义一个虚拟函数。
template <typename T> void noop(T const& t){}
使用虚拟函数。
for (const auto& dummy : input) {
noop(dummy);
}
(void)dummy
有什么改进,除了你可能展示了意图 - 但此时我们正在使用大量的垃圾代码和变通方法,而不是例如for循环! - Moo-Juice(void)dummy
只有部分有效(它不能与基于EDG的编译器一起使用)。 - manliotemplate<typename F>
void repeat(std::size_t n, F&&f){
if(!n) return;
while(--n) f();
std::forward<F>(f)(); // enable rvalue operator()
}
template<class C,class=void>struct has_size:std::false_type{};
template<class C>struct has_size<C,decltype(
std::declval<C>().size(),void()
)>:std::true_type{};
template<typename C>
std::size_t size_helper(C&&c,std::false_type){
using std::begin; using std::end;
return std::distance(begin(c),end(c));
}
template<typename C>
std::size_t size_helper(C&&c, std::true-type){
return c.size();
}
template<typename C>
std::size_t size(C&&c){
return size_helper(c, has_size<C>());
}
然后:
repeat(size( source ),[&]{
std::cout<<".";
});
应该以接近最优的效率与标准容器和数组一起工作。在开始重复代码之前,它会计算 forward_list
中的所有元素。
for
循环。 - Moo-Juiceinput.size()
。 - billz