Récemment, on
m'a rappelé pourquoi je
considÚre que c'est une mauvaise idée de donner aux débutants du C ++. C'est une
mauvaise idée , car en C ++, un vrai gùchis est un gùchis beau, mais perverti, tragique et étonnant. Malgré l'état actuel de la communauté, cet article n'est pas dirigé contre
le C ++
moderne . Au lieu de cela, elle poursuit partiellement l'
article de Simon Brand,
«L'initialisation en C ++ est fou», et en partie c'est un message pour chaque étudiant qui veut commencer ses études en regardant dans l'abßme.
Objections typiques des étudiants lorsqu'ils apprennent l'apprentissage de C:
- "Est-ce que quelqu'un d'autre l'utilise?"
- "C'est stupide."
- "Pourquoi apprenons-nous le C?"
- «Nous devons apprendre quelque chose de mieux, par exemple le C ++» ( rires )
Il semble que de nombreux étudiants pensent que l'apprentissage du C n'a pas vraiment d'importance (de l'auteur: ce n'est pas le cas) et devraient plutÎt commencer par le C ++. Examinons une des raisons pour lesquelles il s'agit d'une proposition absurde:
créer une putain de variable . Dans l'article d'origine, Simon Brand a suggéré que le lecteur connaissait déjà les bizarreries de l'initialisation dans les versions antérieures à C ++ 11. Ici, nous regardons certains d'entre eux et allons un peu plus loin.
Permettez-moi de commencer par expliquer que dans cet article mon opinion personnelle, et
non la position officielle de l'UniversitĂ© de Drexel, oĂč j'enseigne au DĂ©partement de gĂ©nie Ă©lectrique et informatique. Mes cours sont gĂ©nĂ©ralement inclus dans le cadre d'un programme d'ingĂ©nierie, plutĂŽt qu'en informatique, c'est-Ă -dire qu'ils concernent davantage la programmation systĂšme et les systĂšmes embarquĂ©s.
Résumé dans un GIF
u / AlexAlabuzhev sur Reddit a rĂ©ussi Ă relire cet article en entier dans un gif. (Je pense que c'est l'Ćuvre originale de
Timur Dumler )
Je n'ai rien contre C ++, mais il y a beaucoup de tout ce dont vous n'avez pas besoin à un stade précoce.
Câest tout. Rentre chez toi. Faites une promenade avec le chien. Lavez le linge. Appelez maman et dites que vous l'aimez. Essayez une nouvelle recette. Rien Ă lire ici les gars. En fait, pensez Ă quel point les ingĂ©nieurs (c'est-Ă -dire moi) sont incapables de transmettre leurs pensĂ©es ...
Tout, j'ai persuadé comme je le pouvais!
Alors, tu es toujours là ? Vrai soldat. Si je pouvais, je te donnerais une médaille! Et un délicieux lait au chocolat!
Revenons maintenant Ă notre ... programmation habituelle.Initialisation en C
Entrée
Tout d'abord, envisagez l'
initialisation en C car elle est similaire à C ++ pour des raisons de compatibilité. Ce sera assez rapide, car C est tellement ennuyeux et simple (
ahem ). Chaque dĂ©butant apprend cette initialisation par cĆur, car en C, cela fonctionne diffĂ©remment que dans de nombreux nouveaux langages typĂ©s statiquement. Il existe soit une initialisation par dĂ©faut pour les valeurs acceptables, soit une erreur de compilation est levĂ©e.
int main() {
int i;
printf("%d", i);
}
C ,
i (
i ). , ,
int i = 0;, . ,
, , , , ,
0.
, .
int i;
int main() {
printf("%d", i);
}
, ?
i â .
.
, . , ? . , .
, .
struct A {
int i;
};
int main() {
struct A a;
printf("%d", a.i);
}
.
a . .
$ gcc -Wuninitalized a.c
a.c: In function âmainâ:
a.c:9:5: warning: âa.iâ is used uninitialized in this function [-Wuninitialized]
printf("%d\n", a.i);
C . : 1) , 2) 3) .
struct A {
int i;
} const default_A = {0};
void init_A(struct A *ptr) {
ptr->i = 0;
}
int main() {
/* helper function */
struct A a1;
init_A(&a1);
/* during definition;
* Initialize each member, in order.
* Any other uninitialized members are implicitly
* initialized as if they had static storage duration. */
struct A a2 = {0};
/* Error! (Well, technically) Initializer lists are 'non-empty' */
/* struct A a3 = {}; */
/* ...or use designated initializers if C99 or later */
struct A a4 = {.i = 0};
/* default value */
struct A a5 = default_A;
}
, C, , . , ,
0.
C++
1.
C++, .
, C ,
.
C++, , , âŠ
⊠C++ C. :
struct A {
int i;
};
int main() {
A a;
std::cout << a.i << std::endl;
}
C++ . C
A, . C++
a ,
.
A ,
, . « », :
struct A {
A(){}
int i;
}
, .
g++ 8.2.1 ,
clang++ 7.0.1 (
-Wuninitialized). , .
$ g++ -Wuninitalized -O2 a.cpp
a.cpp: In function âint main()â:
a.cpp:9:20: warning: âa.A::iâ is used uninitialized in this function [-Wuninitialized]
std::cout << a.i << std::endl;
C.
A::i?
2.
, , ? , C++ , ? (
)
struct A {
int i;
};
int main() {
A a = {.i = 0};
std::cout << a.i << std::endl;
}
$ g++ -Wuninitialized -O2 -pedantic-errors a.cpp
a.cpp: In function âint main()â:
a.cpp:9:12: error: C++ designated initializers only available with -std=c++2a or -std=gnu++2a [-Wpedantic]
A a = {.i = 0};
. C++ C++20. C++, 2020 . , C++ 21 , C. ,
-pedantic-errors gcc.
?
struct A {
int i;
};
int main() {
A a = {0};
std::cout << a.i << std::endl;
}
$ g++ -Wuninitialized -O2 -pedantic-errors a.cpp
$
.
A a = {}; ,
a.i.
A . ?
C++11 ( ) C, , C. , , , . . ?
- .
- «».
, ? , . ,
A, . ,
int i,
.
! - : ! .
C++11 ⊠.
? , C++ .
. . , , . . , , , .
3.
,
C++
(
)!
i :
struct A {
A() : i(0) {}
int i;
};
i . â :
struct A {
A() { i = 0; }
int i;
};
, ( ).
C++11 (, ).
struct A {
int i = 0; // default member initializer, available in C++11 and later
};
, ,
i 0,
A . , A
i, . :
struct A {
A(int i = 0) : i(i) {}
int i;
};
int main() {
A a1;
A a2(1);
std::cout << a1.i << " " << a2.i << std::endl;
}
$ g++ -pedantic-errors -Wuninitialized -O2 a.cpp
$ ./a.out
0 1
. A a(); , a, A. ? - - , .
! . . C++, . !
4.
. ,
C++, . g++ (8.2.1),
gnu++1y, C++14 GNU. , g++ C++17. « ?» â . , .
, C++11, ,
. , ?
. : .
. FAQ:
C++11 , .
(
{thing1, thing2, ...},
braced-init-list) :
#include <iostream>
struct A {
int i;
};
int main() {
A a1; // default initialization -- as before
A a2{}; // direct-list-initialization with empty list
A a3 = {}; // copy-list-initialization with empty list
std::cout << a1.i << " " << a2.i << " " << a3.i << std::endl;
}
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
a.cpp: In function âint main()â:
a.cpp:9:26: warning: âa1.A::iâ is used uninitialized in this function [-Wuninitialized]
std::cout << a1.i << " " << a2.i << " " << a3.i « std::endl;
, , ?
a1.i. , , .
A a{}; ,
A a = {};.
a braced-init-list. ,
A a = {}; â
copy-list-initialization (
). ,
A a; .
7/8 (,
C++11):
A .
- , A .
- , .
- int i{}
i, 0.
?
int main() {
A a1{0};
A a2{{}};
A a3{a1};
std::cout << a1.i << " " << a2.i << " " << a3.i << std::endl;
}
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
$
a1.i 0,
a2.i ,
a3 â ,
a1. , ,
? , rvalue, , pr-, x-, gl-⊠, .
, C++11 , C++17 C++20 . , C++, - . . , C++17, . !
? ? ? , , ?
5. ,
,
A ?
, :
- //,
- /
- ( C++11, )
- ( C++17)
- (
using Base::Base;, C++17)
:
#include <iostream>
struct A {
A(){};
int i;
};
int main() {
A a{};
std::cout << a.i << std::endl;
}
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
a.cpp: In function âint main()â:
a.cpp:8:20: warning: âa.A::iâ is used uninitialized in this function [-Wuninitialized]
std::cout << a.i << std::endl;
A , .
7 :
A .- - braced-init-list , .
- , , ,
a.i .
, ?
struct A {
A() = default;
};
, . , A .
struct A {
A();
};
A::A() = default;
, . A(){} , .
? C++20 : , :). ? ! .
:
#include <iostream>
class A {
int i;
friend int main();
};
int main() {
A a{};
std::cout << a.i << std::endl;
}
A â , ,
i ,
main .
. . ,
a.i , ?
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
$
. , . ,
a.i 0, :
- A, 2.
- , , braced-init-list , 3.
- , , 4.
- , ( ).
:
#include <iostream>
class A {
int i;
friend int main();
};
int main() {
A a = {1};
std::cout << a.i << std::endl;
}
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
a.cpp: In function âint main()â:
a.cpp:7:13: error: could not convert â{1}â from â<brace-enclosed initializer list>â to âAâ
A a = {1};
A , :
- A, 2.
- .
1 A, .
:
#include <iostream>
struct A {
A(int i) : i(i) {}
A() = default;
int i;
};
int main() {
A a{};
std::cout << a.i << std::endl;
}
, , , : , A . ,
?
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
$
! :
- A, 2.
- , , braced-init-list , 3.
- ( ), , 4.
- , ( ).
:
#include <iostream>
struct A {
A(){}
int i;
};
struct B : public A {
int j;
};
int main() {
B b = {};
std::cout << b.i << " " << b.j << std::endl;
}
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
a.cpp: In function âint main()â:
a.cpp:11:25: warning: âb.B::<anonymous>.A::iâ is used uninitialized in this function [-Wuninitialized]
std::cout << b.i << " " << b.j << std::endl;
b.j ,
b.i . ? !
b .
Stack Overflow,
, , .
. , clang ( ) . .
...
( ) ( ) , !
6.
C++11
std::initializer_list. : ,
std::initializer_list<T>. braced-init-list. , braced-init-list . initializer_list braced-init-list! , , . , ! , ?
struct A {
template <typename T>
A(std::initializer_list<T>) {}
int i;
};
int main() {
A a1{0};
A a2{1, 2, 3};
A a3{"hey", "thanks", "for", "reading!"};
std::cout << a1.i << a2.i << a3.i << std::endl;
}
$ g++ -std=c++17 -pedantic-errors -Wuninitialized -O2 a.cpp
a.cpp: In function âint main()â:
a.cpp:12:21: warning: âa1.A::iâ is used uninitialized in this function [-Wuninitialized]
std::cout << a1.i << a2.i << a3.i << std::endl;
^
a.cpp:12:29: warning: âa2.A::iâ is used uninitialized in this function [-Wuninitialized]
std::cout << a1.i << a2.i << a3.i << std::endl;
^
a.cpp:12:37: warning: âa3.A::iâ is used uninitialized in this function [-Wuninitialized]
std::cout << a1.i << a2.i << a3.i << std::endl;
.
A ,
std::initializer_list<T>. , , ,
i .
T , .
- ,
{0} std::initializer_list<int> 0. {1, 2, 3} std::initializer_list<int> .- braced-init-list
std::initializer_list<const char*> .
: A a{} , . , a{std::initializer_list<int> {}}. , A(std::initializer_list<int>){}.
std::initializer_list STL, :
size,
begin end.
begin end , . , :
#include <vector>
#include <string>
int main() {
std::vector<int> v_1_int{5};
std::vector<int> v_5_ints(5);
std::vector<std::string> v_strs = {"neato!", "blammo!", "whammo!", "egh"};
}
std::vector<T> ,
std::initializer_list<T>, , .
. v_1_int , std::initializer_list<int< init 5.
v_5_ints size_t count, (5) ( 0).
â, :
#include <iostream>
struct A {
A(std::initializer_list<int> l) : i(2) {}
A(int i = 1) : i(i) {}
int i;
};
int main() {
A a1;
A a2{};
A a3(3);
A a4 = {5};
A a5{4, 3, 2};
std::cout << a1.i << " "
<< a2.i << " "
<< a3.i << " "
<< a4.i << " "
<< a5.i << std::endl;
}
, . :
std::initializer_list<int>,
int. , ,
i.
...? , .
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
$ ./a.out
1 1 3 2 2
a1 . , , .
a2 .
A ( ), .
A , .
a3 , braced-init-list,
3 ,
int. ,
4 , ,
std::initializer_list. ,
a5 -
int, ,
a4.
, , (
) , , . , , . ++, .
, â . , . , . , -, , ,
.
, , C++ , ( ). .
. , 5 .
18 .
C++. , , . C++, C++, , .
C C ,
this C.
C â , , , . 18 .
, ,
. .
:
- Lobste.rs
- Hacker News
- Reddit
: ,
. , â . , C++. . , STL C, , . C , , C, , , , , . , C,
, . C++, C++. C++ C++, C.
, C++. .
, .