C ++ 'da bir for döngüsünün başlatma gövdesinde farklı türde iki değişken bildirmek mümkün müdür?
Örneğin:
for(int i=0,j=0 ...
iki tamsayıyı tanımlar. Başlatma gövdesinde int
a ve a tanımlayabilir miyim char
? Bu nasıl halledilebilir?
C ++ 'da bir for döngüsünün başlatma gövdesinde farklı türde iki değişken bildirmek mümkün müdür?
Örneğin:
for(int i=0,j=0 ...
iki tamsayıyı tanımlar. Başlatma gövdesinde int
a ve a tanımlayabilir miyim char
? Bu nasıl halledilebilir?
Yanıtlar:
C ++ 17 : Evet! Yapısal bir bağlayıcı bildirim kullanmalısınız . Sözdizimi gcc ve clang'da yıllardır desteklenmektedir (gcc-7 ve clang-4.0'dan beri) ( clang canlı örneği ). Bu, aşağıdaki gibi bir paketi açmamızı sağlar:
for (auto [i, f, s] = std::tuple{1, 1.0, std::string{"ab"}}; i < N; ++i, f += 1.5) {
// ...
}
Yukarıdakiler size verecektir:
int i
ayarlanır 1
double f
ayarlanır 1.0
std::string s
ayarlanır "ab"
#include <tuple>
Bu tür bir beyan için emin olun .
Bir türü adlandırmak istiyorsanız, tuple
hepsini bende olduğu gibi yazarak içindeki tam türleri belirleyebilirsiniz std::string
. Örneğin:
auto [vec, i32] = std::tuple{std::vector<int>{3, 4, 5}, std::int32_t{12}}
Bunun özel bir uygulaması bir harita üzerinde yineleme yapmak, anahtar ve değeri elde etmek,
std::unordered_map<K, V> m = { /*...*/ };
for (auto& [key, value] : m) {
// ...
}
Burada canlı bir örneğe bakın
C ++ 14 : C ++ 11 ile aynı işlemi yapabilirsiniz (aşağıda) tür tabanlı std::get
. std::get<0>(t)
Aşağıdaki örnek yerine , sahip olabilirsiniz std::get<int>(t)
.
C ++ 11 : ikiden fazla nesne için std::make_pair
olduğu gibi bunu yapmanızı sağlar 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
iki argümanı a std::pair
. Elemanlara .first
ve ile erişilebilir .second
.
İkiden fazla nesne için, bir 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
herhangi bir sayıda argümanın bir demetini oluşturacak (elbette bazı teknik sınırlamalarla) varyasyonlu bir şablondur. Elemanlara indeks ilestd::get<INDEX>(tuple_object)
Döngü organları içinde, kolayca nesneleri takma, hala kullanımda gerek olsa .first
veya std::get
döngü koşulu ve güncelleme ifadesi için için
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 ve C ++ 03 a türlerini açıkça adlandırabilirsiniz std::pair
. Ancak bunu ikiden fazla türe genelleştirmek için standart bir yol yoktur:
for (std::pair<int, std::string> p(5, "Hello World"); p.first < 10; ++p.first) {
std::cout << p.second << std::endl;
}
make_
yazıp bırakabilirsiniz std::pair(1, 1.0)
.
Hayır - ama teknik olarak bir geçici çözüm var (zorunlu olmadığı sürece gerçekten kullanacağımdan değil):
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;
Mümkün değil, ancak şunları yapabilirsiniz:
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
Veya, ek parantezlerin kapsamını f
ve kullanımını açıkça sınırlayın i
:
{
float f;
int i;
for (i = 0,f = 0.0; i < 5; i++)
{
//...
}
}
Bence en iyi yaklaşım xian'ın cevabı .
fakat...
Bu yaklaşım kirli, ancak tüm sürümlerde çözülebilir.
bu yüzden onu makro fonksiyonlarda kullanıyorum.
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
}
Aynı zamanda kullanılabilir declare local variables
ve 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.
}
İyi örnek: makro işlevli.
(En iyi yaklaşım bir for-loop-macro olduğu için kullanılamıyorsa)
#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
Veya olarak başlatmak nullptr
istiyorsanız, bu numarayı kullanabilirsiniz.
ama sert okuma nedeniyle bunu tavsiye etmiyorum.
ve böcek gibi görünüyor.
"Bkz döngü içinde iki tip değişkenleri tanımlamak için bir yol var mı? " Döngüler için yuvalama birden yer aldığı başka bir yol. Georg'un "yapı hilesi" ne karşı diğer bir avantajı, (1) statik ve statik olmayan yerel değişkenlerin bir karışımına sahip olmanıza ve (2) oynatılamayan değişkenlere sahip olmanıza izin vermesidir. Dezavantajı, çok daha az okunabilir olması ve daha az verimli olabilmesidir.
Bir makro tanımlayın:
#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++)
{
//...
}
Unutmayın, değişken kapsamlarınız da bu şekilde for döngüsü içinde olmayacaktır.
{
ve }
.
-std=c++0x
) biçiminde mümkündürfor(auto i=0, j=0.0; ...
, ancak bu olasılık c ++ 0x metinleriyle çakışmak için g ++ - 4.5'te kaldırılmıştır.