จะเปลี่ยนเป็น C ++ 11 ได้อย่างไร


35

ฉันเคยเขียนโปรแกรมใน C ++ มาระยะหนึ่งแล้ว แต่ส่วนใหญ่แล้วสิ่งที่อยู่ตรงกลางของคุณสมบัติระดับต่ำของ C ++ โดยที่ฉันหมายถึงส่วนใหญ่ทำงานร่วมกับพอยน์เตอร์และอาร์เรย์ดิบ ฉันคิดว่าพฤติกรรมนี้เรียกว่าการใช้ C ++ เป็น C กับคลาส อย่างไรก็ตามเรื่องนี้ฉันเพิ่งลอง C เป็นครั้งแรกเท่านั้น ฉันประหลาดใจอย่างมากที่ภาษาอย่าง C # และ Java ซ่อนรายละเอียดเหล่านี้ไว้ในห้องสมุดมาตรฐานที่สะดวกสบายเช่นพจนานุกรมและรายการ

ฉันทราบว่าไลบรารีมาตรฐาน C ++ มีคอนเทนเนอร์มากมายเช่นเวกเตอร์, แผนที่และสตริงเช่นกันและ C ++ 11 จะเพิ่มเฉพาะสิ่งนี้โดยใช้ std :: array และลูป ranged

ฉันจะเรียนรู้ที่จะใช้ประโยชน์จากคุณสมบัติภาษาสมัยใหม่เหล่านี้ได้อย่างไรและเหมาะสมที่สุดกับช่วงเวลาใด ถูกต้องหรือไม่ว่าวิศวกรรมซอฟต์แวร์ใน C ++ ปัจจุบันส่วนใหญ่ไม่มีการจัดการหน่วยความจำด้วยตนเอง

สุดท้ายฉันควรใช้คอมไพเลอร์ตัวใดเพื่อสร้างมาตรฐานใหม่ให้ได้มากที่สุด Visual Studio มีเครื่องมือการดีบักที่ยอดเยี่ยม แต่ VS2012 ก็ดูเหมือนว่าจะมีการสนับสนุน C ++ 11 ที่แย่มาก


2
ฉันจะบอกว่าการเรียก C ++ 11 สนับสนุน VSC55 "แย่มาก" นั้นพูดเกินจริงไปเล็กน้อย แต่แน่นอนว่าอาจจะดีกว่า (รายการเริ่มต้นที่หายไปนั้นน่ารำคาญเป็นพิเศษสำหรับรหัสทดสอบ / ของเล่น) แต่โปรดทราบว่าพวกเขาประกาศว่าพวกเขาจะจัดส่งการอัปเดตคอมไพเลอร์อย่างอิสระจากส่วนที่เหลือของ VS ดังนั้นฉันคาดว่าเราจะหวังว่าจะมีฟีเจอร์ C ++ 11 จำนวนน้อยใน VS2012 ในช่วงปี 2013
Martin Ba

3
ในตอนแรกที่ผมคิดว่ามันแนะนำสำหรับการเรียนรู้ภาษา C ++ 11 จะแปลก แต่เห็นว่าคุณยังคงติดอยู่ในC-ด้วยเรียนที่ดิน ... ทศวรรษที่ผ่านมาผมอ่านนิก / หมู่ของเร่งรัด C เมื่อถึงตอนนี้ฉันกำลังทำ meta-programming แม่แบบอยู่แล้ว (ฉันแค่อ่านเพื่อตรวจสอบ) แต่มันก็ยังรู้สึกเหมือนการเปิดเผย (ฉันใช้มันเป็นฐานสำหรับการสอน C ++ นับตั้งแต่) มาจากC กับ Classesหนังสือเล่มนี้สามารถแสดงภาษาใหม่ทั้งหมดที่คุณไม่เคยรู้มาก่อน มีเพียง 250 หน้าและคุณสามารถเลื่อนไปยังสิ่งเฉพาะ C ++ 11 ได้อย่างรวดเร็ว แต่ IMO เป็นขั้นตอนที่คุ้มค่า
sbi

4
g++ -std=c++11
fredoverflow

คำตอบ:


50

ขั้นแรกกฎง่ายๆ:

  • ใช้std::unique_ptrเป็นตัวชี้สมาร์ทไม่มีค่าใช้จ่าย คุณไม่จำเป็นต้องกังวลกับพอยน์เตอร์ดิบทั้งหมดที่มักจะเกิดขึ้น std::shared_ptrในกรณีส่วนใหญ่ก็ไม่จำเป็นเช่นเดียวกัน ความปรารถนาในการเป็นเจ้าของร่วมแบ่งปันมักจะเป็นการขาดความคิดเกี่ยวกับความเป็นเจ้าของในตอนแรก

  • ใช้std::arrayสำหรับอาร์เรย์ที่มีความยาวคงที่และstd::vectorเป็นแบบไดนามิก

  • ใช้อัลกอริทึมทั่วไปอย่างกว้างขวางโดยเฉพาะ:

    • <algorithm>
    • <numeric>
    • <iterator>
    • <functional>
  • ใช้งานได้ทุกที่autoและdecltype()ได้รับประโยชน์ โดยเฉพาะอย่างยิ่งเมื่อคุณต้องการที่จะประกาศสิ่ง แต่ชนิดที่คุณไม่สนใจเกี่ยวกับเช่น iterator autoหรือประเภทแม่แบบที่ซับซ้อนการใช้งาน decltype()เมื่อคุณต้องการที่จะประกาศสิ่งในแง่ของประเภทของสิ่งอื่นใช้

  • ทำสิ่งต่าง ๆ ที่ปลอดภัยเมื่อคุณสามารถ เมื่อคุณมีคำยืนยันที่บังคับใช้ค่าคงที่กับสิ่งใดประเภทหนึ่งตรรกะนั้นสามารถรวมศูนย์ในรูปแบบใดประเภทหนึ่งได้ และนี่ไม่จำเป็นต้องทำสำหรับค่าใช้จ่ายรันไทม์ใด ๆ นอกจากนี้ควรไปโดยไม่บอกว่าควรใช้สไตล์แบบ C ( (T)x) เพื่อหลีกเลี่ยงความชัดเจน (และสามารถค้นหาได้!) C ++ - สไตล์คาสท์ (เช่น, static_cast)

  • ในที่สุดรู้ว่ากฎของสาม:

    • destructor
    • คัดลอกคอนสตรัค
    • ผู้ประกอบการที่ได้รับมอบหมาย

    ได้กลายเป็นกฎข้อที่ห้าด้วยการเพิ่มตัวสร้างการย้ายและตัวดำเนินการกำหนดการย้าย และเข้าใจการอ้างอิงค่า rvalue โดยทั่วไปและวิธีหลีกเลี่ยงการคัดลอก

C ++ เป็นภาษาที่ซับซ้อนดังนั้นมันจึงเป็นเรื่องยากที่จะอธิบายลักษณะวิธีการที่ดีที่สุดที่จะใช้ทั้งหมดของมัน แต่แนวทางการพัฒนา C ++ ที่ดีนั้นไม่ได้เปลี่ยนพื้นฐานด้วย C ++ 11 คุณควรยังคงชอบคอนเทนเนอร์ที่มีการจัดการหน่วยความจำมากกว่าการจัดการหน่วยความจำด้วยตนเองตัวชี้สมาร์ททำให้ง่ายต่อการทำเช่นนี้

ฉันจะบอกว่า C ++ ที่ทันสมัยเป็นอิสระจากการจัดการหน่วยความจำแบบแมนนวลส่วนใหญ่ข้อดีของรูปแบบหน่วยความจำของ C ++ ก็คือมันสามารถกำหนดได้ การจัดสรรคืนที่คาดการณ์ได้ทำให้มีประสิทธิภาพที่คาดการณ์ได้มากขึ้น

สำหรับคอมไพเลอร์นั้น G ++ และ Clang นั้นทั้งคู่แข่งขันกันในแง่ของคุณสมบัติ C ++ 11 และทันกับข้อบกพร่องของพวกเขาอย่างรวดเร็ว ฉันไม่ได้ใช้ Visual Studio ดังนั้นฉันจึงไม่สามารถพูดหรือทำเพื่ออะไร

ในที่สุดหมายเหตุเกี่ยวกับstd::for_each: หลีกเลี่ยงโดยทั่วไป

transform, accumulateและerase- remove_ifเป็นสิ่งที่ดีเก่าทำงานmap, และfold filterแต่for_eachเป็นเรื่องทั่วไปมากกว่าและมีความหมายน้อยกว่า - มันไม่ได้แสดงเจตนาใดๆ นอกเหนือจากการวนซ้ำ นอกจากนั้นก็ใช้ในสถานการณ์เดียวกับช่วง-based forและเป็นไวยากรณ์หนักแม้ในขณะที่ใช้จุดฟรี พิจารณา:

for (const auto i : container)
    std::cout << i << '\n';

std::for_each(container.begin(), container.end(), [](int i) {
    std::cout << i << '\n';
});

for (const auto i : container)
    frobnicate(i);

std::for_each(container.begin(), container.end(), frobnicate);

6
มีหลักการผูกมัดกฎของหัวแม่มือเหล่านี้หรือไม่? ดูเหมือนจะเป็นรายการคำแนะนำที่ดี แต่ ... ในฐานะที่เป็นคนนอกที่มาถึงคำถามนี้ผ่านทาง Google คำตอบของคุณช่วยฉันเลือก C ++ 11 ได้อย่างไรและใช้มันโดยไม่ห่อหุ้มเพลา C ++ ?
Robert Harvey

3
+1 สำหรับรายการ แต่ฉันมี nitpick ขนาดเล็ก: เมื่อ (ถูกต้อง) คำเตือนต่อผมคาดว่าจะมีช่วงที่ใช้สำหรับห่วงเป็นแทนดีกว่าธรรมดาstd::for_each for
Fabio Fracassi

@FabioFracassi: โอ๊ะโอ ผมเขียนธรรมดาเพื่อความคมชัดกับstd::for_eachไม่ได้กับช่วง-based ฉันได้ลบมันเพื่อหลีกเลี่ยงความสับสน
Jon Purdy

1
std::for_each()ฉันจะอัปเดตถ้ามันไม่ได้สำหรับ เมื่อคุณมีแลมบ์ดามันจะดีกว่าforวงแบบดั้งเดิมอย่างแน่นอน ด้วยforลูปที่ขึ้นอยู่กับช่วงซึ่งอาจไม่ใช่กรณีนี้ แต่คุณไม่ได้เขียน " forลูปที่อิงตามช่วง"
sbi

@sbi: ในใจของฉันคำว่า " forloop" รวมถึง " forloop -based loop" ฉันได้แก้ไขพร้อมคำอธิบายเพิ่มเติมและตัวอย่างเพื่อขอขอบคุณ
Jon Purdy

12

เป็นจุดเริ่มต้น:

  • หยุดใช้char*สำหรับสตริง ใช้std::stringหรือstd::wstringดูรหัสของคุณให้สั้นลงอ่านง่ายขึ้นและปลอดภัยขึ้น
  • หยุดใช้อาร์เรย์สไตล์ C (สิ่งที่ประกาศไว้[ ]) และใช้std::vectorหรือคลาสคอนเทนเนอร์อื่นที่เหมาะสม สิ่งที่ดีเกี่ยวกับการstd::vectorที่มันรู้ถึงความยาวของมันมันทำความสะอาดเนื้อหาเมื่อมันออกนอกขอบเขตมันง่ายที่จะย้ำมากกว่าและมันทำให้ตัวเองใหญ่ขึ้นเมื่อคุณเพิ่มรายการเพิ่มเติม แต่มีคอลเลกชันอื่น ๆ ที่อาจทำงานได้ดียิ่งขึ้นสำหรับสถานการณ์ของคุณ
  • ใช้std::unique_ptr- และเรียนรู้std::moveเกือบจะทันที เนื่องจากสิ่งนี้อาจส่งผลให้วัตถุที่ไม่สามารถคัดแยกได้บางครั้งความเกียจคร้านอาจส่งคุณไปยังบางครั้งstd::shared_ptr- และคุณอาจมีกรณีการใช้งานของแท้std::shared_ptrเช่นกัน
  • ใช้autoเมื่อประกาศตัววนซ้ำและชนิดที่ขึ้นอยู่กับการประกาศก่อนหน้านี้ (เช่นก่อนหน้านี้คุณประกาศเวกเตอร์ของบางอย่างตอนนี้คุณกำลังประกาศบางสิ่งใช้auto)
  • ใช้ขั้นตอนวิธีและfor_eachมากกว่า "ดิบ" เมื่อใดก็ตามที่คุณสามารถเพราะมันอะไหล่อื่น ๆ จากการอ่านห่วงคุณอย่างระมัดระวังที่จะสรุปว่าคุณอยู่ในความเป็นจริง iterating กว่าเก็บทั้ง ฯลฯ ถ้าคอมไพเลอร์ของคุณสนับสนุน "ช่วง" for_eachแล้วใช้มันมากกว่า เรียนรู้ขั้นตอนวิธีการโทรที่น่ารำคาญเหมือนiota, generate, accumulate, find_ifและอื่น ๆ
  • ใช้ lambdas - เป็นวิธีที่ง่ายในการใช้อัลกอริทึม พวกเขายังเปิดประตูให้มากขึ้น

อย่าทำงานหนักเกินไปเกี่ยวกับคอมไพเลอร์ที่จะใช้ การขาด "แย่มากน่ากลัว" ของการสนับสนุน C ++ 11 ใน VS2012 คือไม่มีเทมเพลตแบบแปรปรวน (ใช่แล้วคุณเพิ่งจะใช้เทมเพลต Variadic) และเครื่องมือ{}เริ่มต้นไม่อยู่ที่นั่น ฉันต้องการมันเช่นกัน แต่ฉันก็แทบจะหยุดใช้เครื่องมือพัฒนาที่มีประโยชน์อยู่

สิ่งที่สองที่ต้องทำหลังจากยอมรับstd::คือเริ่มคิด RAII ทุกเวลาที่คุณมี

  • เริ่มการกระทำ
  • ชุดของการกระทำกับสิ่งที่คุณได้รับจากการเริ่มต้นการกระทำ
  • การดำเนินการล้างข้อมูลที่ต้องเกิดขึ้นแม้ในกรณีที่มีข้อยกเว้น

จากนั้นสิ่งที่คุณมีคือตัวสร้างจำนวนหน้าที่สมาชิกและตัวทำลาย เขียนชั้นเรียนที่ดูแลคุณ คุณอาจไม่ต้องเขียน ctor และ dtor การวางshared_ptrเป็นตัวแปรสมาชิกของคลาสเป็นตัวอย่างของ RAII - คุณไม่ได้เขียนรหัสการจัดการหน่วยความจำ แต่เมื่ออินสแตนซ์ของคุณไม่อยู่ในขอบเขตสิ่งที่ถูกต้องจะเกิดขึ้น ขยายความคิดที่ครอบคลุมสิ่งต่าง ๆ เช่นการปิดไฟล์การปล่อยมือจับล็อค ฯลฯ และรหัสจะได้ง่ายขึ้นและเล็กลง (ในขณะที่กำจัดการรั่วไหล) ต่อหน้าต่อตาของคุณ

ถ้าคุณรู้สึกมั่นใจจริงๆล้างprintfในความโปรดปรานของcoutกำจัดมาโคร ( #defineสิ่งที่) และเริ่มต้นการเรียนรู้บางส่วน "สำนวนขั้นสูง" เช่น PIMPL ฉันมีหลักสูตรทั้งหมดเกี่ยวกับเรื่องนี้ที่ Pluralsight ซึ่งคุณสามารถดูได้โดยใช้การทดลองใช้ฟรี


2
ฉันชอบวิธีที่คุณประชดประชันเกี่ยวกับเขาที่ไม่ได้ใช้เทมเพลต Variadic ทุกเวลาเร็ว ๆ นี้ แต่ฉันคิดว่าการเริ่มต้นเครื่องแบบหายไปนั้นขาดสิ่งที่สำคัญมากสำหรับการเขียนโปรแกรมทุกวัน
sbi

อดใจรอไม่ไหวที่จะพบรายการเริ่มต้น ... กำลังรอดูว่าเราจะรับพวกเขาไปเมื่อไหร่ ...
Kate Gregory

การขาดที่สำคัญอีกประการหนึ่งใน VS2012 คือ "การอ้างอิง rvalue v3" นั่นคือตัวสร้างการย้ายแบบอัตโนมัติและการกำหนดย้าย
Mr.C64

3

ฉันจะเรียนรู้ที่จะใช้ประโยชน์จากคุณสมบัติภาษาสมัยใหม่เหล่านี้ได้อย่างไรและเหมาะสมที่สุดกับช่วงเวลาใด

โดยการเขียนโปรแกรม ประสบการณ์เป็นวิธีที่ดีที่สุดในการเรียนรู้

C ++ 11 มีคุณสมบัติใหม่มากมาย (อัตโนมัติ, rvalue, สมาร์ทพอยน์เตอร์ใหม่ - เพื่อตั้งชื่อไม่กี่) จุดเริ่มต้นที่ดีที่สุดคือการเริ่มใช้พวกเขาและอ่านเกี่ยวกับพวกเขาเมื่อใดก็ตามที่คุณสามารถทำได้และเมื่อใดก็ตามที่คุณพบบทความที่น่าสนใจ

ถูกต้องหรือไม่ว่าวิศวกรรมซอฟต์แวร์ใน C ++ ปัจจุบันส่วนใหญ่ไม่มีการจัดการหน่วยความจำด้วยตนเอง

ขึ้นอยู่กับสิ่งที่คุณต้องทำ แอพพลิเคชั่นส่วนใหญ่สามารถหลบหนีได้ด้วยพอยน์เตอร์อัจฉริยะและลืมเกี่ยวกับการจัดการหน่วยความจำ ยังคงมีแอปพลิเคชั่นที่ไม่สามารถหลบหนีได้ง่าย (เช่นหากต้องการตำแหน่งใหม่หรือตัวจัดสรรหน่วยความจำแบบกำหนดเองไม่ว่าด้วยเหตุผลใดก็ตาม)

หากคุณต้องการใช้ Qt คุณจะต้องใช้กฎของพวกเขาสำหรับการจัดการหน่วยความจำ

ฉันควรใช้คอมไพเลอร์ใดเพื่อสร้างมาตรฐานใหม่ให้ได้มากที่สุด

สิ่งที่คุณมีอยู่ในมือที่รองรับมาตรฐานล่าสุด:

แต่ไม่มีคอมไพเลอร์รองรับคุณสมบัติทั้งหมด


-7

มหาวิทยาลัยของฉันยังคงใช้ภาษา C ++ เพื่อการสอน ฉันตั้งโปรแกรมด้วย C ++ เป็นเวลา 5 ปีและตอนนี้ฉันเป็นนักศึกษาระดับบัณฑิตศึกษา แน่นอนตอนนี้ฉันใช้ Java, Ruby และอื่น ๆ ฉันขอแนะนำให้คุณอย่ารีบร้อนเกินไปกับคุณสมบัติเหล่านั้นในภาษาเช่น Java จากประสบการณ์และความคิดเห็นของฉันหลังจากคุณสมบัติระดับต่ำของ C ++ คุณควรพิจารณาหัวข้อต่างๆเช่นการเขียนโปรแกรมทั่วไปด้วย C / C ++ เช่นการสร้างคลาสเทมเพลตฟังก์ชันเทมเพลตการเขียนทับตัวดำเนินการวิธีเสมือนตัวชี้อัจฉริยะ สำหรับส่วนการออกแบบเชิงวัตถุนั้นมีคุณสมบัติหลายอย่างที่ C ++ มีอยู่และ Java ไม่ได้เหมือนมรดกหลายตัว การรับมรดกนั้นทรงพลัง แต่ก็อันตรายเช่นกัน ระดับการใช้งานของการออกแบบเชิงวัตถุใน C ++ เป็นหัวข้อที่ดีเช่นกัน การสื่อสารระหว่างกระบวนการเธรดก็มีความสำคัญใน C ++ เช่นกัน

สำหรับคอมไพเลอร์และดีบั๊ก ฉันรู้ว่า visual studio นั้นยอดเยี่ยมมาก แต่ฉันขอแนะนำให้คุณเรียนรู้ GDB, Valgrind และ Make Still และใช้เครื่องมือเหล่านี้ได้ดี Microsoft นั้นยอดเยี่ยม แต่ก็ทำสิ่งต่าง ๆ ให้คุณมากเกินไป ในฐานะนักเรียนคุณต้องเรียนรู้สิ่งต่าง ๆ ที่ Microsoft ทำเช่นกัน สำหรับคอมไพเลอร์ G ++ นั้นดีจาก GNU

หลังจากหลายปีที่ผ่านมาฉันรู้สึกว่าสิ่งที่สำคัญที่สุดคือคุณสมบัติระดับต่ำเช่นอาเรย์ดิบ เวกเตอร์เป็นเพียงอาร์เรย์ไดนามิก นี่คือคำแนะนำของฉันมีบางสิ่งที่อาจเป็นอัตวิสัยเกินไปเพียงแค่คิดในสิ่งที่ถูก


6
คำถามนี้จะตอบคำถามได้อย่างไร คำถามไม่เกี่ยวกับการเรียนรู้ C ++ โดยทั่วไป แต่เปลี่ยนเป็น C ++ 11
Roc Martí
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.