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

发布于 2024-08-29 23:12:47 字数 181 浏览 11 评论 0原文

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

例如:

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

眼趣 2024-09-05 23:12:47

不 - 但从技术上讲,有一个解决方法(除非被迫,否则我实际上不会使用它):

for(struct { int a; char b; } s = { 0, 'a' } ; s.a < 5 ; ++s.a) 
{
    std::cout << s.a << " " << s.b << std::endl;
}

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;
}
独自唱情﹋歌 2024-09-05 23:12:47

不可能,但您可以这样做:

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

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

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

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++)
    {
       //...
    }
}
铃予 2024-09-05 23:12:47

C++17是的!您应该使用结构化绑定声明。自 gcc-7 和 clang-4.0 起,gcc 和 clang 就支持该语法(clang 实例)。这允许我们像这样解包一个元组:

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

上面的代码将为您提供:

  • int i set to 1
  • double f set to 1.0
  • std::string s 设置为 "ab"

确保为此类声明#include

如果您想命名一个类型,您可以通过像我使用 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(t),而不是下面示例中的 std::get<0>(t)


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 << '\n';
}

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) << '\n'; // cout Hello world
    std::get<2>(t).push_back(std::get<0>(t)); // add counter value to the vector
}

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

在 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 << '\n'; // cout Hello world
    v.push_back(i); // add counter value to the vector
}

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

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

C++17: Yes! You should use a structured binding declaration. The syntax has been supported in gcc and clang since 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{"ab"}}; i < N; ++i, f += 1.5) {
    // ...
}

The above will give you:

  • int i set to 1
  • double f set to 1.0
  • std::string s set to "ab"

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

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++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 << '\n';
}

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) << '\n'; // 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 << '\n'; // 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 << '\n';
}
浅沫记忆 2024-09-05 23:12:47

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

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

只需在它们自己的作用域中声明它们即可。

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.

箹锭⒈辈孓 2024-09-05 23:12:47

我认为最好的方法是xian的回答

但是...


# 嵌套for循环

这种方法很脏,但可以在所有版本中解决。

所以,我经常在宏函数中使用它。

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
    }

其他 1.

它还可以用于声明局部变量初始化全局变量

float globalFloat;

for(int localInt=0, /* decalre local variable */ \
    _=1;_;_=0)

    for(globalFloat=2.f; localInt<3; localInt++) /* initialize global variable */
    {
        // do.
    }

附加 2.

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

(如果无法使用最佳方法,因为它是一个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-语句技巧

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

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

但由于阅读困难,我不推荐这样做。

这看起来像是错误。

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.

请你别敷衍 2024-09-05 23:12:47

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

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.

爱本泡沫多脆弱 2024-09-05 23:12:47

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

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

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
}
红尘作伴 2024-09-05 23:12:47

定义宏:

#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 循环内。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文