C++ 是否可以在 for 循环中声明两个不同类型的变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2687392/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:22:07  来源:igfitidea点击:

Is it possible to declare two variables of different types in a for loop?

c++scopedeclarationfor-loop

提问by Nathan Osman

Is it possible to declare two variables of different types in the initialization body of a for loop in C++?

是否可以在 C++ 的 for 循环的初始化体中声明两个不同类型的变量?

For example:

例如:

for(int i=0,j=0 ...

defines two integers. Can I define an intand a charin the initialization body? How would this be done?

定义两个整数。我可以在初始化体中定义 anint和 achar吗?这将如何完成?

采纳答案by Ryan Haining

C++17: Yes!You should use a structured binding declaration. The syntax has been supported in gcc and clang for years (since gcc-7 and clang-4.0) (clang live example). This allows us to unpack a tuple like so:

C++17是的!您应该使用结构化绑定声明。gcc 和 clang 多年来一直支持该语法(从 gcc-7 和 clang-4.0 开始)(clang live example)。这允许我们像这样解包一个元组:

for (auto [i, f, s] = std::tuple{1, 1.0, std::string{"ab"}}; i < N; ++i, f += 1.5) {
    // ...
}

The above will give you:

以上将为您提供:

  • int iset to 1
  • double fset to 1.0
  • std::string sset to "ab"
  • int i设置 1
  • double f设置 1.0
  • std::string s设置 "ab"

Make sure to #include <tuple>for this kind of declaration.

确保#include <tuple>为这种声明。

You can specify the exact types inside the tupleby typing them all out as I have with the std::string, if you want to name a type. For example:

如果你想命名一个类型,你可以tuple通过像我一样将它们全部输入出来来指定里面的确切类型std::string。例如:

auto [vec, i32] = std::tuple{std::vector<int>{3, 4, 5}, std::int32_t{12}}

A specific application of this is iterating over a map, getting the key and value,

它的一个具体应用是迭代地图,获取键和值,

std::unordered_map<K, V> m = { /*...*/ };
for (auto& [key, value] : m) {
   // ...
}

See a live example here

在此处查看现场示例



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++14:您可以通过添加基于类型的std::get. 因此std::get<0>(t),您可以将std::get<int>(t).



C++11: std::make_pairallows you to do this, as well as std::make_tuplefor more than two objects.

C++11std::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_pairwill return the two arguments in a std::pair. The elements can be accessed with .firstand .second.

std::make_pair将返回 a 中的两个参数std::pair。可以使用.first和访问元素.second

For more than two objects, you'll need to use a std::tuple

对于两个以上的对象,您需要使用 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_tupleis 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)

std::make_tuple是一个可变参数模板,它将构造一个包含任意数量参数的元组(当然有一些技术限制)。元素可以通过索引访问std::get<INDEX>(tuple_object)

Within the for loop bodies you can easily alias the objects, though you still need to use .firstor std::getfor the for loop condition and update expression

在 for 循环体中,您可以轻松地为对象设置别名,但您仍然需要使用.firstor std::getfor 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 and C++03You can explicitly name the types of a std::pair. There is no standard way to generalize this to more than two types though:

C++98 和 C++03您可以显式命名 a 的类型std::pair。但是,没有标准方法可以将其概括为两种以上类型:

for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
    std::cout << p.second << std::endl;
}

回答by Georg Fritzsche

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

回答by MK.

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 fand iusing additional brackets:

或者,明确限制fi使用附加括号的范围:

{
    float f; 
    int i;
    for (i = 0,f = 0.0; i < 5; i++)
    {
       //...
    }
}

回答by zmbush

You can't declare multiple types in the initialization, but you can assign to multiple types E.G.

不能在初始化中声明多个类型,但是可以给多个类型赋值 EG

{
   int i;
   char x;
   for(i = 0, x = 'p'; ...){
      ...
   }
}

Just declare them in their own scope.

只需在它们自己的范围内声明它们。

回答by mgcation

I think best approach is xian's answer.

我认为最好的方法是xian's answer

but...

但...



# Nested for loop

#嵌套for循环

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.

附加 1。

It can also be used to declare local variablesand initialize global variables.

它也可以用于declare local variablesinitialize 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.

附加 2。

Good example : with macro function.

很好的例子:具有宏功能。

(If best approachcan't be used because it is a for-loop-macro)

(如果最好的方法不能使用,因为它是一个 for 循环宏)

#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 语句技巧

if (A* a=nullptr);
else
    for(...) // a is visible

If you want initialize to 0or nullptr, you can use this trick.

如果你想初始化为0or nullptr,你可以使用这个技巧。

but I don't recommend this because of hard reading.

但我不推荐这个,因为很难阅读。

and it seems like bug.

这似乎是错误。

回答by tgoodhart

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.

有关嵌套多个 for 循环的另一种方法,请参阅“有没有办法在 for 循环中定义两种类型的变量?”。与 Georg 的“结构技巧”相比,另一种方式的优势在于它 (1) 允许您混合使用静态和非静态局部变量,以及 (2) 它允许您拥有不可复制的变量。缺点是它的可读性要差得多,而且效率也可能较低。

回答by Ryan Favale

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.

请记住,您的变量范围也不会以这种方式位于 for 循环内。

回答by loyola

Also you could use like below in C++.

您也可以在 C++ 中使用如下所示。

int j=3;
int i=2;
for (; i<n && j<n ; j=j+2, i=i+2){
  // your code
}