是否可以在C ++中的for循环的初始化主体中声明两个不同类型的变量?
例如:
for(int i=0,j=0 ...
定义两个整数。我可以在初始化正文中定义an int
和a char
吗?怎么做?
是否可以在C ++中的for循环的初始化主体中声明两个不同类型的变量?
例如:
for(int i=0,j=0 ...
定义两个整数。我可以在初始化正文中定义an int
和a char
吗?怎么做?
Answers:
C ++ 17:是的!您应该使用结构化绑定声明。多年来,gcc和clang支持该语法(自gcc-7和clang-4.0起)(clang live示例)。这使我们可以像这样拆开元组的包装:
for (auto [i, f, s] = std::tuple{1, 1.0, std::string{"ab"}}; i < N; ++i, f += 1.5) {
// ...
}
以上将为您提供:
int i
调成 1
double f
调成 1.0
std::string s
调成 "ab"
确保#include <tuple>
进行此类声明。
如果要命名类型,可以tuple
通过键入全部内容来指定内的确切类型std::string
。例如:
auto [vec, i32] = std::tuple{std::vector<int>{3, 4, 5}, std::int32_t{12}}
具体的应用是遍历地图,获取键和值,
std::unordered_map<K, V> m = { /*...*/ };
for (auto& [key, value] : m) {
// ...
}
在这里查看现场示例
C ++ 14:您可以通过添加基于类型来与C ++ 11(下文)相同std::get
。因此std::get<0>(t)
,您可以拥有而不是下面的示例std::get<int>(t)
。
C ++ 11:std::make_pair
允许您以及std::make_tuple
两个以上的对象执行此操作。
for (auto p = std::make_pair(5, std::string("Hello World")); p.first < 10; ++p.first) {
std::cout << p.second << std::endl;
}
std::make_pair
将在中返回两个参数std::pair
。可以使用.first
和来访问元素.second
。
对于两个以上的对象,您需要使用 std::tuple
for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
std::get<0>(t) < 10;
++std::get<0>(t)) {
std::cout << std::get<1>(t) << std::endl; // cout Hello world
std::get<2>(t).push_back(std::get<0>(t)); // add counter value to the vector
}
std::make_tuple
是一个可变参数模板,它将构造任意数量的参数的元组(当然有一些技术限制)。元素可以通过索引访问std::get<INDEX>(tuple_object)
在for循环体内,您仍然可以轻松地为对象加上别名,尽管您仍然需要使用for .first
或std::get
for循环条件并更新表达式
for (auto t = std::make_tuple(0, std::string("Hello world"), std::vector<int>{});
std::get<0>(t) < 10;
++std::get<0>(t)) {
auto& i = std::get<0>(t);
auto& s = std::get<1>(t);
auto& v = std::get<2>(t);
std::cout << s << std::endl; // cout Hello world
v.push_back(i); // add counter value to the vector
}
C ++ 98和C ++ 03您可以显式命名std::pair
。但是,没有标准的方法可以将其概括为两种以上的类型:
for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
std::cout << p.second << std::endl;
}
make_
和编写代码std::pair(1, 1.0)
。
否-但是从技术上讲,有一种解决方法(除非强制执行,否则我实际上不会使用它):
for(struct { int a; char b; } s = { 0, 'a' } ; s.a < 5 ; ++s.a)
{
std::cout << s.a << " " << s.b << std::endl;
}
struct { int a=0; char b='a'; } s;
不可能,但是您可以执行以下操作:
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
或者,明确限制范围f
并i
使用其他括号:
{
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
}
我认为最好的方法是西安的答案。
但...
这种方法很脏,但是可以解决所有版本。
因此,我经常在宏函数中使用它。
for(int _int=0, /* make local variable */ \
loopOnce=true; loopOnce==true; loopOnce=false)
for(char _char=0; _char<3; _char++)
{
// do anything with
// _int, _char
}
它也可以用于declare local variables
和initialize global variables
。
float globalFloat;
for(int localInt=0, /* decalre local variable */ \
_=1;_;_=0)
for(globalFloat=2.f; localInt<3; localInt++) /* initialize global variable */
{
// do.
}
很好的例子:具有宏功能。
(如果因为是循环宏而无法使用最佳方法)
#define for_two_decl(_decl_1, _decl_2, cond, incr) \
for(_decl_1, _=1;_;_=0)\
for(_decl_2; (cond); (incr))
for_two_decl(int i=0, char c=0, i<3, i++)
{
// your body with
// i, c
}
if (A* a=nullptr);
else
for(...) // a is visible
如果要初始化为0
或nullptr
,则可以使用此技巧。
但由于阅读困难,我不建议您这样做。
好像是虫子。
请参阅“ 是否可以在for循环中定义两种类型的变量?涉及嵌套多个for循环的另一种方法, ”。与Georg的“结构技巧”相比,另一种方法的优势在于,它(1)允许您混合使用静态和非静态局部变量,并且(2)允许您具有不可复制的变量。不利的一面是它的可读性和效率可能大大降低。
定义一个宏:
#define FOR( typeX,x,valueX, typeY,y,valueY, condition, increments) typeX x; typeY y; for(x=valueX,y=valueY;condition;increments)
FOR(int,i,0, int,f,0.0, i < 5, i++)
{
//...
}
请记住,您的变量作用域也不会以这种方式位于for循环内。
{
和将代码包装在宏中的单独范围中,可以轻松克服该限制}
。
-std=c++0x
)中可能以的形式出现for(auto i=0, j=0.0; ...
,但这种可能性在g ++-4.5中已删除,与c ++ 0x文本一致。