เป็นไปได้ไหมที่จะประกาศสองตัวแปรที่มีชนิดต่างกันในเนื้อความการเริ่มต้นของ for for loop ใน C ++?
ตัวอย่างเช่น:
for(int i=0,j=0 ...
กำหนดจำนวนเต็มสองจำนวน ฉันสามารถนิยามint
a และ a char
ในส่วนเริ่มต้นได้หรือไม่? สิ่งนี้จะเกิดขึ้นได้อย่างไร?
เป็นไปได้ไหมที่จะประกาศสองตัวแปรที่มีชนิดต่างกันในเนื้อความการเริ่มต้นของ for for loop ใน C ++?
ตัวอย่างเช่น:
for(int i=0,j=0 ...
กำหนดจำนวนเต็มสองจำนวน ฉันสามารถนิยามint
a และ a char
ในส่วนเริ่มต้นได้หรือไม่? สิ่งนี้จะเกิดขึ้นได้อย่างไร?
คำตอบ:
C ++ 17 : ใช่! คุณควรใช้การประกาศผลผูกพันโครงสร้าง ไวยากรณ์ได้รับการสนับสนุนใน gcc และเสียงดังกราวเป็นเวลาหลายปี (ตั้งแต่ gcc-7 และ clang-4.0) ( ตัวอย่างเสียงดังกราวสด ) สิ่งนี้ช่วยให้เราสามารถคลายสิ่งอันดับเป็น:
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
เป็นเทมเพลต Variadic ที่จะสร้าง tuple ของจำนวนอาร์กิวเมนต์ใด ๆ (โดยมีข้อ จำกัด ทางเทคนิคบางประการ) องค์ประกอบสามารถเข้าถึงได้โดยดัชนีด้วยstd::get<INDEX>(tuple_object)
ภายใน for loop body คุณสามารถนามแฝงวัตถุได้อย่างง่ายดายแม้ว่าคุณจะต้องใช้.first
หรือstd::get
สำหรับเงื่อนไข loop และ 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 และ 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;
}
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++)
{
//...
}
}
คุณไม่สามารถประกาศหลายประเภทในการเริ่มต้น แต่คุณสามารถกำหนดให้กับ EG หลายประเภท
{
int i;
char x;
for(i = 0, x = 'p'; ...){
...
}
}
เพียงประกาศพวกเขาในขอบเขตของตัวเอง
ผมคิดว่าวิธีที่ดีที่สุดคือคำตอบของซีอาน
แต่...
วิธีนี้สกปรก แต่สามารถแก้ไขได้ทุกเวอร์ชั่น
ดังนั้นฉันมักจะใช้มันในฟังก์ชั่นมาโคร
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.
}
ตัวอย่างที่ดี: ด้วยฟังก์ชั่นมาโคร
(ถ้าวิธีที่ดีที่สุดไม่สามารถใช้ได้เพราะมันเป็น 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 (A* a=nullptr);
else
for(...) // a is visible
หากคุณต้องการเริ่มต้น0
หรือnullptr
คุณสามารถใช้เคล็ดลับนี้
แต่ฉันไม่แนะนำเพราะอ่านยาก
และดูเหมือนว่าข้อผิดพลาด
ดูที่ " มีวิธีกำหนดตัวแปรสองชนิดสำหรับลูปหรือไม่ " สำหรับวิธีอื่นที่เกี่ยวข้องกับการซ้อนซ้อนกันหลายครั้งสำหรับลูป ข้อดีของวิธีอื่น ๆ ในการใช้ "เคล็ดลับ struct" ของ 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++)
{
//...
}
เพียงจำไว้ว่าขอบเขตตัวแปรของคุณจะไม่อยู่ในการวนซ้ำด้วยวิธีนี้เช่นกัน
{
}
นอกจากนี้คุณสามารถใช้เช่นด้านล่างใน C ++
int j=3;
int i=2;
for (; i<n && j<n ; j=j+2, i=i+2){
// your code
}
-std=c++0x
) ในรูปแบบของfor(auto i=0, j=0.0; ...
แต่ความเป็นไปได้นี้ถูกลบใน g ++ - 4.5 เพื่อให้ตรงกับข้อความ c ++ 0x