Recientemente,
recordé por qué
considero que es una mala idea dar a los principiantes C ++. Esta es una
mala idea , porque en C ++ un desastre real es un desastre hermoso, pero pervertido, trágico y sorprendente. A pesar del estado actual de la comunidad, este artículo no está dirigido contra C ++
moderno . Más bien, continúa parcialmente el
artículo de Simon Brand,
"La inicialización en C ++ es una locura", y en parte es un mensaje para cada estudiante que quiera comenzar su educación mirando hacia el abismo.
Objeciones típicas de los estudiantes cuando se les dice acerca de aprender C:
- "¿Alguien más lo está usando?"
- "Esto es estúpido".
- "¿Por qué estamos aprendiendo C?"
- "Debemos aprender algo mejor, por ejemplo, C ++" ( risas )
Parece que muchos estudiantes piensan que aprender C no importa realmente (del autor: no lo es) y deberían comenzar con C ++. Veamos solo una de las razones por las cuales esta es una proposición absurda:
crear una jodida variable . En el artículo original, Simon Brand sugirió que el lector ya estaba familiarizado con las rarezas de la inicialización en versiones anteriores a C ++ 11. Aquí miramos algunos de ellos y vamos un poco más allá.
Permítanme aclarar primero que en este artículo mi opinión personal, y
no la posición oficial de la Universidad de Drexel, donde enseño en el Departamento de Ingeniería Eléctrica e Informática. Mis conferencias generalmente se incluyen en el curso de un programa de ingeniería, en lugar de ciencias de la computación, es decir, se relacionan más con la programación de sistemas y los sistemas integrados.
Resumen en un GIF
u / AlexAlabuzhev en Reddit logró volver a contar todo este artículo en un gif. (Creo que este es el trabajo original de
Timur Dumler )
No tengo nada en contra de C ++, pero hay mucho de todo lo que no necesitas en una etapa temprana.
Eso es todo Vete a casa Sal a caminar con el perro. Lavar la ropa. Llama a mamá y dile que la amas. Prueba una nueva receta. Nada que leer aquí chicos. De hecho, piense en lo mal que los ingenieros (es decir, yo) son capaces de transmitir sus pensamientos ...
¡Todo, lo convencí como pude!
Entonces, ¿sigues aquí? Verdadero soldado. ¡Si pudiera, te daría una medalla! Y deliciosa leche con chocolate!
Ahora volvamos a nuestra ... programación habitual.Inicialización en C
Entrada
Primero, considere la
inicialización en C porque es similar a C ++ por razones de compatibilidad. Será bastante rápido, porque C es muy aburrido y simple (
ejem ). Todo principiante aprende esta inicialización de memoria, porque en C funciona de manera diferente que en muchos nuevos lenguajes estáticamente tipados. Hay una inicialización predeterminada para valores aceptables o se produce un error de compilación.
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++. .
, .