portaldacalheta.pt
  • หลัก
  • การเพิ่มขึ้นของระยะไกล
  • ผู้คนและทีมงาน
  • การวางแผนและการพยากรณ์
  • การออกแบบ Ux
ส่วนหลัง

ข้อผิดพลาด C ++ ที่พบบ่อยที่สุด 10 อันดับแรกที่นักพัฒนาทำ



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

ข้อผิดพลาดทั่วไป # 1: การใช้คู่ 'ใหม่' และ 'ลบ' ไม่ถูกต้อง

ไม่ว่าเราจะพยายามแค่ไหนก็ยากมากที่จะปลดปล่อยหน่วยความจำที่จัดสรรแบบไดนามิกทั้งหมดให้เป็นอิสระ แม้ว่าเราจะทำได้ แต่ก็มักไม่ปลอดภัยจากข้อยกเว้น ให้เราดูตัวอย่างง่ายๆ:



void SomeMethod() { ClassA *a = new ClassA; SomeOtherMethod(); // it can throw an exception delete a; }

หากมีข้อยกเว้นเกิดขึ้นวัตถุ“ a” จะไม่ถูกลบ ตัวอย่างต่อไปนี้แสดงวิธีที่ปลอดภัยและสั้นกว่าในการทำเช่นนั้น ใช้ auto_ptr ซึ่งเลิกใช้แล้วใน C ++ 11 แต่มาตรฐานเก่ายังคงใช้กันอย่างแพร่หลาย สามารถแทนที่ด้วย C ++ 11 unique_ptr หรือ scoped_ptr จาก Boost ได้ถ้าเป็นไปได้



void SomeMethod() { std::auto_ptr a(new ClassA); // deprecated, please check the text SomeOtherMethod(); // it can throw an exception }

ไม่ว่าจะเกิดอะไรขึ้นหลังจากสร้างออบเจ็กต์“ a” แล้วจะถูกลบทันทีที่การเรียกใช้โปรแกรมออกจากขอบเขต



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

ข้อผิดพลาดทั่วไป # 2: ผู้ทำลายเสมือนที่ถูกลืม

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



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

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



class MyString : public std::string { ~MyString() { // ... } }; int main() { std::string *s = new MyString(); delete s; // May not invoke the destructor defined in MyString }

เพื่อหลีกเลี่ยงปัญหา C ++ ดังกล่าววิธีที่ปลอดภัยกว่าในการนำคลาส / เทมเพลตจากไลบรารีมาตรฐานมาใช้ซ้ำคือการใช้การสืบทอดหรือองค์ประกอบส่วนตัว

ข้อผิดพลาดทั่วไป # 3: การลบอาร์เรย์ด้วยการ“ ลบ” หรือใช้ตัวชี้อัจฉริยะ

ข้อผิดพลาดทั่วไป # 3

ฟังก์ชันคือฟังก์ชันที่เขียนไว้แล้วและจัดให้เป็นส่วนหนึ่งของระบบ

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

การใช้ตัวชี้อัจฉริยะเช่น auto_ptr, unique_ptr, shared_ptr กับอาร์เรย์ก็ไม่ถูกต้องเช่นกัน เมื่อตัวชี้อัจฉริยะดังกล่าวออกจากขอบเขตจะเรียกตัวดำเนินการลบโดยไม่มีเครื่องหมายวงเล็บ [] ซึ่งส่งผลให้เกิดปัญหาเดียวกันกับที่อธิบายไว้ข้างต้น หากจำเป็นต้องใช้ตัวชี้อัจฉริยะสำหรับอาร์เรย์คุณสามารถใช้ scoped_array หรือ shared_array จาก Boost หรือความเชี่ยวชาญเฉพาะทาง unique_ptr

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

ข้อผิดพลาดทั่วไป # 4: การส่งคืนวัตถุในเครื่องโดยการอ้างอิง

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

Complex& SumComplex(const Complex& a, const Complex& b) { Complex result; ….. return result; } Complex& sum = SumComplex(a, b);

ตอนนี้วัตถุ 'ผลรวม' จะชี้ไปที่ 'ผลลัพธ์' ของวัตถุในพื้นที่ แต่วัตถุ 'ผลลัพธ์' อยู่ที่ไหนหลังจากเรียกใช้ฟังก์ชัน SumComplex? ไม่มีที่ไหนเลย มันตั้งอยู่บนสแต็ก แต่หลังจากฟังก์ชั่นส่งคืนสแต็กกลับถูกคลายออกและอ็อบเจ็กต์ในเครื่องทั้งหมดจากฟังก์ชันถูกทำลาย ในที่สุดสิ่งนี้จะส่งผลให้เกิดพฤติกรรมที่ไม่ได้กำหนดแม้กระทั่งสำหรับประเภทดั้งเดิม เพื่อหลีกเลี่ยงปัญหาด้านประสิทธิภาพบางครั้งอาจใช้การเพิ่มประสิทธิภาพค่าส่งคืน:

Complex SumComplex(const Complex& a, const Complex& b) { return Complex(a.real + b.real, a.imaginar + b.imaginar); } Complex sum = SumComplex(a, b);

สำหรับคอมไพเลอร์ส่วนใหญ่ในปัจจุบันหากบรรทัดส่งคืนมีตัวสร้างของอ็อบเจ็กต์โค้ดจะได้รับการปรับให้เหมาะสมเพื่อหลีกเลี่ยงการคัดลอกที่ไม่จำเป็นทั้งหมด - คอนสตรัคเตอร์จะดำเนินการโดยตรงกับอ็อบเจ็กต์ 'sum'

ข้อผิดพลาดทั่วไป # 5: การใช้การอ้างอิงไปยังทรัพยากรที่ถูกลบ

ปัญหา C ++ เหล่านี้เกิดขึ้นบ่อยกว่าที่คุณคิดและมักจะพบในแอปพลิเคชันมัลติเธรด ให้เราพิจารณารหัสต่อไปนี้:

หัวข้อที่ 1:

Connection& connection= connections.GetConnection(connectionId); // ...

หัวข้อที่ 2:

connections.DeleteConnection(connectionId); // …

หัวข้อที่ 1:

connection.send(data);

ในตัวอย่างนี้หากเธรดทั้งสองใช้ ID การเชื่อมต่อเดียวกันสิ่งนี้จะส่งผลให้เกิดพฤติกรรมที่ไม่ได้กำหนด ข้อผิดพลาดในการละเมิดการเข้าถึงมักจะพบได้ยากมาก

s corp หรือ c corp ความแตกต่าง

ในกรณีเหล่านี้เมื่อมีเธรดมากกว่าหนึ่งเธรดเข้าถึงทรัพยากรเดียวกันจะมีความเสี่ยงมากที่จะเก็บพอยน์เตอร์หรือการอ้างอิงไปยังรีซอร์สเนื่องจากเธรดอื่นบางเธรดสามารถลบได้ การใช้ตัวชี้อัจฉริยะกับการนับอ้างอิงจะปลอดภัยกว่ามากเช่น shared_ptr จาก Boost ใช้การดำเนินการของอะตอมเพื่อเพิ่ม / ลดตัวนับอ้างอิงดังนั้นจึงปลอดภัยต่อเธรด

ข้อผิดพลาดทั่วไป # 6: อนุญาตให้มีข้อยกเว้นออกจากผู้ทำลาย

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

class A { public: A(){} ~A() { writeToLog(); // could cause an exception to be thrown } }; // … try { A a1; A a2; } catch (std::exception& e) { std::cout << 'exception caught'; }

ในโค้ดด้านบนหากมีข้อยกเว้นเกิดขึ้นสองครั้งเช่นระหว่างการทำลายวัตถุทั้งสองคำสั่ง catch จะไม่ถูกดำเนินการ เนื่องจากมีข้อยกเว้นสองข้อควบคู่กันไม่ว่าจะเป็นประเภทเดียวกันหรือคนละประเภทก็ตามสภาพแวดล้อมรันไทม์ C ++ ไม่ทราบวิธีจัดการและเรียกฟังก์ชันยุติซึ่งส่งผลให้การดำเนินการของโปรแกรมสิ้นสุดลง

ดังนั้นกฎทั่วไปคือ: ไม่อนุญาตให้มีข้อยกเว้นออกจากผู้ทำลาย แม้ว่ามันจะน่าเกลียด แต่ก็ต้องมีการป้องกันข้อยกเว้นเช่นนี้:

try { writeToLog(); // could cause an exception to be thrown } catch (...) {}

ข้อผิดพลาดทั่วไป # 7: การใช้“ auto_ptr” (ไม่ถูกต้อง)

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

auto_ptr a(new ClassA); // deprecated, please check the text auto_ptr b = a; a->SomeMethod(); // will result in access violation error

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

  1. ห้ามใช้ auto_ptr ภายในคอนเทนเนอร์ STL การคัดลอกคอนเทนเนอร์จะทำให้คอนเทนเนอร์ต้นทางมีข้อมูลที่ไม่ถูกต้อง อัลกอริทึม STL บางอย่างอาจทำให้ 'auto_ptr' ใช้ไม่ได้

  2. อย่าใช้ auto_ptr เป็นอาร์กิวเมนต์ของฟังก์ชันเนื่องจากจะนำไปสู่การคัดลอกและปล่อยให้ค่าที่ส่งผ่านไปยังอาร์กิวเมนต์ไม่ถูกต้องหลังจากเรียกฟังก์ชัน

  3. หากใช้ auto_ptr สำหรับสมาชิกข้อมูลของคลาสต้องแน่ใจว่าได้ทำสำเนาที่ถูกต้องภายในตัวสร้างสำเนาและตัวดำเนินการกำหนดหรือไม่อนุญาตการดำเนินการเหล่านี้โดยกำหนดให้เป็นแบบส่วนตัว

    มูลค่าของตัวเลือกการใส่
  4. เมื่อใดก็ตามที่เป็นไปได้ให้ใช้ตัวชี้อัจฉริยะที่ทันสมัยอื่น ๆ แทน auto_ptr

ข้อผิดพลาดทั่วไป # 8: การใช้ตัวทำซ้ำและการอ้างอิงที่ไม่ถูกต้อง

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

vector v; v.push_back(“string1”); string& s1 = v[0]; // assign a reference to the 1st element vector::iterator iter = v.begin(); // assign an iterator to the 1st element v.push_back(“string2”); cout << s1; // access to a reference of the 1st element cout << *iter; // access to an iterator of the 1st element

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

ข้อผิดพลาดทั่วไป # 9: การส่งผ่านวัตถุตามค่า

ข้อผิดพลาดทั่วไป # 9

คุณคงทราบดีว่าการส่งผ่านวัตถุตามมูลค่าเป็นความคิดที่ดีเนื่องจากผลกระทบด้านประสิทธิภาพ หลายคนปล่อยไว้แบบนั้นเพื่อหลีกเลี่ยงการพิมพ์อักขระพิเศษหรืออาจคิดว่าจะกลับมาเพิ่มประสิทธิภาพในภายหลัง โดยปกติจะไม่เคยทำสำเร็จและด้วยเหตุนี้จึงนำไปสู่โค้ดและโค้ดที่มีประสิทธิภาพน้อยกว่าซึ่งมีแนวโน้มที่จะเกิดพฤติกรรมที่ไม่คาดคิด:

class A { public: virtual std::string GetName() const {return 'A';} … }; class B: public A { public: virtual std::string GetName() const {return 'B';} ... }; void func1(A a) { std::string name = a.GetName(); ... } B b; func1(b);

รหัสนี้จะรวบรวม การเรียกใช้ฟังก์ชัน“ func1” จะสร้างสำเนาบางส่วนของอ็อบเจ็กต์“ b” กล่าวคือจะคัดลอกเฉพาะคลาส“ A” ของอ็อบเจ็กต์“ b” ไปยังอ็อบเจ็กต์“ a” (“ ปัญหาการแบ่งส่วน”) ดังนั้นภายในฟังก์ชันจะเรียกเมธอดจากคลาส“ A” แทนเมธอดจากคลาส“ B” ซึ่งส่วนใหญ่จะไม่ใช่สิ่งที่ใครบางคนเรียกใช้ฟังก์ชันนี้

ปัญหาที่คล้ายกันเกิดขึ้นเมื่อพยายามจับข้อยกเว้น ตัวอย่างเช่น:

class ExceptionA: public std::exception; class ExceptionB: public ExceptionA; try { func2(); // can throw an ExceptionB exception } catch (ExceptionA ex) { writeToLog(ex.GetDescription()); throw; }

เมื่อข้อยกเว้นของประเภท ExceptionB ถูกโยนออกจากฟังก์ชัน“ func2” มันจะถูกจับโดยบล็อก catch แต่เนื่องจากปัญหาการแบ่งส่วนเฉพาะบางส่วนจากคลาส ExceptionA เท่านั้นที่จะถูกคัดลอกวิธีการที่ไม่ถูกต้องจะถูกเรียกและโยนซ้ำด้วย จะโยนข้อยกเว้นที่ไม่ถูกต้องไปยังบล็อกทดลองจับภายนอก

ในการสรุปให้ส่งผ่านวัตถุโดยการอ้างอิงเสมอไม่ใช่ตามค่า

ข้อผิดพลาดทั่วไป # 10: การใช้ Conversion ที่กำหนดโดยผู้ใช้โดยตัวสร้างและตัวดำเนินการแปลง

แม้แต่ Conversion ที่ผู้ใช้กำหนดเองก็มีประโยชน์มากในบางครั้ง แต่อาจนำไปสู่ ​​Conversion ที่ไม่ได้คาดการณ์ซึ่งหาได้ยากมาก สมมติว่ามีคนสร้างไลบรารีที่มีคลาสสตริง:

class String { public: String(int n); String(const char *s); …. }

วิธีแรกมีไว้เพื่อสร้างสตริงที่มีความยาว n และวิธีที่สองมีไว้เพื่อสร้างสตริงที่มีอักขระที่กำหนด แต่ปัญหาจะเริ่มทันทีที่คุณมีสิ่งนี้:

String s1 = 123; String s2 = ‘abc’;

ในตัวอย่างด้านบน s1 จะกลายเป็นสตริงขนาด 123 ไม่ใช่สตริงที่มีอักขระ“ 123” ตัวอย่างที่สองประกอบด้วยเครื่องหมายคำพูดเดี่ยวแทนอัญประกาศคู่ (ซึ่งอาจเกิดขึ้นโดยไม่ได้ตั้งใจ) ซึ่งจะส่งผลให้มีการเรียกตัวสร้างตัวแรกและสร้างสตริงที่มีขนาดใหญ่มาก นี่เป็นตัวอย่างง่ายๆจริงๆและยังมีกรณีที่ซับซ้อนอีกมากมายที่นำไปสู่ความสับสนและการแปลงที่คาดเดาไม่ได้ซึ่งหาได้ยากมาก มีกฎทั่วไป 2 ข้อในการหลีกเลี่ยงปัญหาดังกล่าว:

  1. กำหนดตัวสร้างด้วยคำหลักที่ชัดเจนเพื่อไม่อนุญาตให้มีการแปลงโดยนัย

    ฉันจะทำอย่างไรกับโหนด js
  2. แทนที่จะใช้ตัวดำเนินการแปลงให้ใช้วิธีการสนทนาที่ชัดเจน ต้องพิมพ์มากกว่านี้เล็กน้อย แต่อ่านได้สะอาดกว่ามากและช่วยหลีกเลี่ยงผลลัพธ์ที่คาดเดาไม่ได้

สรุป

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

ที่เกี่ยวข้อง: วิธีการเรียนรู้ภาษา C และ C ++: รายการที่ดีที่สุด

การเพิ่มประสิทธิภาพโค้ด: วิธีที่ดีที่สุดในการเพิ่มประสิทธิภาพ

การบริหารโครงการ

การเพิ่มประสิทธิภาพโค้ด: วิธีที่ดีที่สุดในการเพิ่มประสิทธิภาพ
ออกแบบอนาคต: เครื่องมือและผลิตภัณฑ์รอเราอยู่

ออกแบบอนาคต: เครื่องมือและผลิตภัณฑ์รอเราอยู่

การออกแบบ Ux

โพสต์ยอดนิยม
ความจริงเสมือนในอุตสาหกรรมยานยนต์
ความจริงเสมือนในอุตสาหกรรมยานยนต์
วิธีใช้ Bootstrap และสร้าง. NET Projects
วิธีใช้ Bootstrap และสร้าง. NET Projects
วิธีทำความเข้าใจและประเมินการลงทุนในกองทุนอสังหาริมทรัพย์ส่วนบุคคล
วิธีทำความเข้าใจและประเมินการลงทุนในกองทุนอสังหาริมทรัพย์ส่วนบุคคล
4 ไปวิจารณ์ภาษา
4 ไปวิจารณ์ภาษา
ข้อมูลเบื้องต้นเกี่ยวกับ Magento: การนำทางในระบบนิเวศอีคอมเมิร์ซยอดนิยม
ข้อมูลเบื้องต้นเกี่ยวกับ Magento: การนำทางในระบบนิเวศอีคอมเมิร์ซยอดนิยม
 
วีซ่า H-1B: การเดินทางของนักพัฒนา iOS จากฮอนดูรัสไปยัง Silicon Valley
วีซ่า H-1B: การเดินทางของนักพัฒนา iOS จากฮอนดูรัสไปยัง Silicon Valley
ข้อผิดพลาดทั่วไปในการสื่อสารกับลูกค้า: จะไม่ทำให้ลูกค้าของคุณผิดหวังได้อย่างไร
ข้อผิดพลาดทั่วไปในการสื่อสารกับลูกค้า: จะไม่ทำให้ลูกค้าของคุณผิดหวังได้อย่างไร
การออกแบบที่คาดหวัง: วิธีสร้างประสบการณ์ผู้ใช้ที่มีมนต์ขลัง
การออกแบบที่คาดหวัง: วิธีสร้างประสบการณ์ผู้ใช้ที่มีมนต์ขลัง
กราฟิก 3 มิติ: บทช่วยสอน WebGL
กราฟิก 3 มิติ: บทช่วยสอน WebGL
การออกแบบ VUI - Voice User Interface
การออกแบบ VUI - Voice User Interface
โพสต์ยอดนิยม
  • การจัดการข้อยกเว้นในการบูตสปริง
  • ราคาเท่าไหร่คะ
  • โหนด js ทำอะไร
  • cfos ใส่ใจอะไร
  • หลักการออกแบบความสามัคคีและความหลากหลาย
  • วิธีทำใบรับรอง aws
  • แสดง js กับ node js
หมวดหมู่
  • การเพิ่มขึ้นของระยะไกล
  • ผู้คนและทีมงาน
  • การวางแผนและการพยากรณ์
  • การออกแบบ Ux
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt