问题
Is it possible to declare two variables of different types in the initialization body of a for loop in C++?
For example:
for(int i=0,j=0 ...
defines two integers. Can I define an int and a char in the initialization body? How would this be done?
回答1:
Not possible, but you can do:
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
Or, explicitly limit the scope of f and i using additional brackets:
{
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
}
回答2:
No - but technically there is a work-around (not that i'd actually use it unless forced to):
for(struct { int a; char b; } s = { 0, 'a' } ; s.a < 5 ; ++s.a)
{
std::cout << s.a << " " << s.b << std::endl;
}
回答3:
C++17: Yes! You should use a structured binding declaration. The syntax is supported in gcc-7 and clang-4.0 (clang live example). This allows us to unpack a tuple like so:
for (auto [i, f, s] = std::tuple{1, 1.0, std::string{"abc"}}; i < N; ++i) {
// ...
}
The above will give you:
int iset to1double fset to1.0std::string sset to"abc"
Make sure to #include <tuple> for this kind of declaration.
You can specify the exact types inside the tuple by typing them all out as I have with the std::string, if you want to name a type. For example:
auto [vec, i32] = std::tuple{std::vector<int>{3, 4, 5}, std::int32_t{12}}
C++14: You can do the same as C++11 (below) with the addition of type-based std::get. So instead of std::get<0>(t) in the below example, you can have std::get<int>(t).
C++11: std::make_pair allows you to do this, as well as std::make_tuple for more than two objects.
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 will return the two arguments in a std::pair. The elements can be accessed with .first and .second.
For more than two objects, you'll need to use a 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 is a variadic template that will construct a tuple of any number of arguments (with some technical limitations of course). The elements can be accessed by index with std::get<INDEX>(tuple_object)
Within the for loop bodies you can easily alias the objects, though you still need to use .first or std::get for the for loop condition and update expression
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 and C++03 You can explicitly name the types of a std::pair. There is no standard way to generalize this to more than two types though:
for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
std::cout << p.second << std::endl;
}
回答4:
You can't declare multiple types in the initialization, but you can assign to multiple types E.G.
{
int i;
char x;
for(i = 0, x = 'p'; ...){
...
}
}
Just declare them in their own scope.
回答5:
See "Is there a way to define variables of two types in for loop?" for another way involving nesting multiple for loops. The advantage of the other way over Georg's "struct trick" is that it (1) allows you to have a mixture of static and non-static local variables and (2) it allows you to have non-copyable variables. The downside is that it is far less readable and may be less efficient.
回答6:
I think best approach is xian's answer.
but...
# Nested for loop
This approach is dirty, but can solve at all version.
so, I often use it in macro functions.
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
}
Additional 1.
It can also be used to declare local variables and 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.
}
Additional 2.
Good example : with macro function.
(If best approach can't be used because it is a for-loop-macro)
#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-statement trick
if (A* a=nullptr);
else
for(...) // a is visible
If you want initialize to 0 or nullptr, you can use this trick.
but I don't recommend this because of hard reading.
and it seems like bug.
回答7:
Also you could use like below in C++.
int j=3;
int i=2;
for (; i<n && j<n ; j=j+2, i=i+2){
// your code
}
回答8:
Define a macro:
#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++)
{
//...
}
Just remember, your variable scopes will not be within the for loop this way either.
来源:https://stackoverflow.com/questions/2687392/is-it-possible-to-declare-two-variables-of-different-types-in-a-for-loop