最近,
我 想起了为什么我
认为给初学者C ++
是个 坏主意 。 这是一个
坏 主意 ,因为在C ++中,真正的混乱是一个美丽但又变态,悲剧和惊人的混乱。 尽管社区处于当前状态,但本文并非针对
现代 C ++。 相反,她部分地继续了Simon Brand的
文章 “ C ++中的初始化非常疯狂” ,部分地它是向想要开始深渊学习的每个学生传达的信息。
当学生被告知要学习C时,他们通常会提出异议:
- “有人在用吗?”
- “这很愚蠢”
- “我们为什么要学习C?”
- “我们必须学习更好的东西,例如C ++”( 笑声 )
似乎许多学生认为学习C并不重要(作者:不是),而应该从C ++开始。 让我们看一下这是一个荒谬主张的原因之一:
创建一个他妈的变量 。 在最初的文章中,Simon Brand建议读者已经熟悉C ++ 11之前版本中的初始化奇异之处。 在这里,我们来看其中一些,并进一步介绍。
首先,请允许我在本文中阐明我的个人观点,而
不是我在电气和计算机工程系任教的Drexel大学
的正式职位。 我的演讲通常包含在工程程序课程中,而不是计算机科学课程,也就是说,它们与系统编程和嵌入式系统的关系更大。
一个GIF中的摘要
u / Reddit上的AlexAlabuzhev设法以gif格式重述了整篇文章。 (我认为这是
Timur Dumler的原创作品)
我对C ++毫无抵触,但在初期阶段,您不需要很多东西。
仅此而已。 回家吧 与狗散步。 洗衣服。 打电话给妈妈说你爱她。 尝试新食谱。 没什么在这里读的家伙。 实际上,请考虑一下工程师(即我)传达思想的能力有多差...
一切,我尽力说服!
所以,你还在吗? 真正的士兵。 如果可以的话,我会给你一枚奖章! 还有美味的巧克力牛奶!
现在回到我们通常的编程。用C初始化
参赛作品
首先,考虑一下
C中的初始化,因为出于兼容性方面的考虑
,它类似于C ++。 它将非常快,因为C非常无聊且简单(
ahem )。 每个初学者都会认真学习这种初始化,因为在C中,它的工作方式不同于许多新的静态类型语言。 缺省值为可接受的值初始化,否则将引发编译错误。
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++. .
, .