لقد تم تذكيرنا مؤخرًا بالسبب الذي يجعلني
أعتبر أنه من الجيد إعطاء C ++ للمبتدئين. هذه
فكرة سيئة ، لأن الفوضى الحقيقية في C ++ هي فوضى جميلة ولكنها مأساوية ومدهشة. على الرغم من الوضع الحالي للمجتمع ، فإن هذه المقالة ليست موجهة ضد C ++
الحديث . بدلاً من ذلك ، تواصلت جزئيًا مع
مقال سيمون براند ،
"التهيئة في C ++ مجنونة" ، وهي في جزء منها رسالة إلى كل طالب يرغب في بدء تعليمه بالنظر إلى الهاوية.
اعتراضات الطلاب النموذجية عند إخبارك عن تعلم C:
- "هل يستخدمه شخص آخر؟"
- "هذا غبي."
- "لماذا نتعلم C؟"
- "يجب أن نتعلم شيئًا أفضل ، على سبيل المثال ، C ++" ( ضحك )
يبدو أن العديد من الطلاب يعتقدون أن تعلم C لا يهم حقًا (من المؤلف: لا) ويجب أن يبدأ بـ C ++ بدلاً من ذلك. لنلقِ نظرة فقط على أحد الأسباب وراء كون هذا اقتراحًا سخيفًا:
إنشاء متغير سخيف . في المقالة الأصلية ، اقترح سيمون براند أن القارئ كان على دراية بالفعل بشذوذ التهيئة في الإصدارات السابقة لـ C ++ 11. هنا ننظر إلى بعض منهم ونذهب أبعد من ذلك بقليل.
اسمحوا لي أولاً أن أوضح أنه في هذا المقال رأيي الشخصي ،
وليس الموقف الرسمي لجامعة دريكسيل ، حيث أقوم بالتدريس في قسم الهندسة الكهربائية وهندسة الحاسبات. عادةً ما يتم تضمين محاضراتي في برنامج هندسي ، بدلاً من علوم الكمبيوتر ، أي أنها ترتبط أكثر ببرمجة النظام والأنظمة المدمجة.
ملخص في GIF واحد
تمكنت u / AlexAlabuzhev على Reddit من إعادة كتابة هذه المقالة بالكامل في صورة واحدة. (أعتقد أن هذا هو العمل الأصلي
لتيمور دوملر )
ليس لدي أي شيء ضد C ++ ، ولكن هناك الكثير من الأشياء التي لا تحتاجها في مرحلة مبكرة.
هذا كل شيء. العودة إلى المنزل. تأخذ المشي مع الكلب. اغسل الغسيل. اتصل بأمي وقل أنك تحبها. جرب وصفة جديدة. لا شيء لقراءة هنا يا رفاق. في الحقيقة ، فكر في مدى قدرة المهندسين (أي أنا) على نقل أفكارهم ...
كل شيء ، أقنعت ما أستطيع!
هل ما زلت هنا؟ جندي حقيقي. إذا استطعت ، سأمنحك ميدالية! وحليب الشوكولاته اللذيذ!
عاد الآن إلى البرمجة المعتادة لدينا.التهيئة في C
الدخول
أولاً ، ضع
في الاعتبار
التهيئة في C لأنها تشبه C ++ لأسباب التوافق. سيكون الأمر سريعًا جدًا ، لأن C ممل جدًا وبسيط (
مهم ). يتعلم كل مبتدئ هذا التهيئة عن ظهر قلب ، لأنه في 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++. .
, .