ฉันเห็นว่ามีคำตอบที่ดีจำนวนหนึ่งอยู่แล้ว บางอย่างที่ฉันจะทำซ้ำ แต่บางครั้งคุณเพียงต้องการที่จะใส่สิ่งต่าง ๆ ในคำพูดของคุณเอง ฉันจะแสดงความคิดเห็นด้วยตัวอย่างจาก C ++ เพราะนั่นคือภาษาที่ฉันคุ้นเคยมากที่สุด
สิ่งที่จำเป็นคือไม่ฉลาด การอนุมานประเภทเป็นสิ่งจำเป็นเพื่อทำให้คุณสมบัติภาษาอื่น ๆ เป็นประโยชน์ ใน C ++ เป็นไปได้ที่จะมีประเภทที่ไม่สามารถอ่านได้
struct {
double x, y;
} p0 = { 0.0, 0.0 };
// there is no name for the type of p0
auto p1 = p0;
C ++ 11 เพิ่ม lambdas ซึ่งไม่สามารถพูดได้
auto sq = [](int x) {
return x * x;
};
// there is no name for the type of sq
การอนุมานประเภทยังสนับสนุนแม่แบบ
template <class x_t>
auto sq(x_t const& x)
{
return x * x;
}
// x_t is not known until it is inferred from an expression
sq(2); // x_t is int
sq(2.0); // x_t is double
แต่คำถามของคุณคือ "ทำไมฉัน, โปรแกรมเมอร์, ต้องการที่จะอนุมานประเภทของตัวแปรของฉันเมื่อฉันอ่านรหัสหรือไม่มันเร็วกว่าสำหรับทุกคนที่อ่านประเภทมากกว่าที่จะคิดว่ามีประเภทใด?"
การอนุมานประเภทจะลบความซ้ำซ้อน เมื่อพูดถึงการอ่านโค้ดบางครั้งมันอาจจะเร็วกว่าและง่ายกว่าที่จะมีข้อมูลซ้ำซ้อนในโค้ด แต่ความซ้ำซ้อนสามารถป้องกันข้อมูลที่เป็นประโยชน์ได้ ตัวอย่างเช่น:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
ไม่คุ้นเคยกับไลบรารีมาตรฐานสำหรับโปรแกรมเมอร์ C ++ เพื่อระบุว่า i เป็นตัววนซ้ำi = v.begin()
ดังนั้นการประกาศชนิดที่ชัดเจนจึงมีค่า จำกัด การปรากฏตัวของมันจะปิดบังรายละเอียดที่สำคัญกว่า (เช่นi
ชี้ไปที่จุดเริ่มต้นของเวกเตอร์) คำตอบที่ดีโดย @amon ให้ตัวอย่างที่ดียิ่งขึ้นของการใช้คำฟุ่มเฟื่อยมากกว่ารายละเอียดที่สำคัญ ในทางตรงกันข้ามการใช้การอนุมานประเภทให้ความสำคัญกับรายละเอียดที่สำคัญมากขึ้น
std::vector<int> v;
auto i = v.begin();
ในขณะที่การอ่านรหัสเป็นสิ่งสำคัญมันไม่เพียงพอในบางจุดคุณจะต้องหยุดอ่านและเริ่มเขียนรหัสใหม่ ความซ้ำซ้อนในรหัสทำให้การแก้ไขรหัสช้าลงและหนักขึ้น ตัวอย่างเช่นสมมติว่าฉันมีส่วนของรหัสต่อไปนี้:
std::vector<int> v;
std::vector<int>::iterator i = v.begin();
ในกรณีที่ฉันต้องเปลี่ยนประเภทค่าของเวกเตอร์เพื่อเปลี่ยนรหัสเป็นสองเท่า:
std::vector<double> v;
std::vector<double>::iterator i = v.begin();
ในกรณีนี้ฉันต้องแก้ไขโค้ดในที่สองแห่ง ตรงกันข้ามกับการอนุมานประเภทโดยที่รหัสต้นฉบับคือ:
std::vector<int> v;
auto i = v.begin();
และรหัสแก้ไข:
std::vector<double> v;
auto i = v.begin();
โปรดทราบว่าตอนนี้ฉันต้องเปลี่ยนโค้ดหนึ่งบรรทัดเท่านั้น คาดการณ์สิ่งนี้กับโปรแกรมขนาดใหญ่และการอนุมานประเภทสามารถเผยแพร่การเปลี่ยนแปลงประเภทได้เร็วกว่าที่คุณสามารถทำได้ด้วยโปรแกรมแก้ไข
ความซ้ำซ้อนในรหัสสร้างความเป็นไปได้ของข้อบกพร่อง เมื่อใดก็ตามที่รหัสของคุณขึ้นอยู่กับข้อมูลสองชิ้นที่ถูกเก็บไว้เทียบเท่าอาจมีความผิดพลาดได้ ตัวอย่างเช่นมีความไม่สอดคล้องกันระหว่างสองประเภทในคำสั่งนี้ซึ่งอาจไม่ได้ตั้งใจ:
int pi = 3.14159;
ความซ้ำซ้อนทำให้ความตั้งใจที่จะแยกแยะได้ยากขึ้น ในบางกรณีการอนุมานประเภทนั้นสามารถอ่านและเข้าใจได้ง่ายกว่าเพราะง่ายกว่าข้อกำหนดชนิดที่ชัดเจน พิจารณาส่วนของรหัส:
int y = sq(x);
ในกรณีที่sq(x)
ส่งกลับint
ก็ไม่ได้เป็นที่เห็นได้ชัดว่าy
เป็นint
เพราะมันเป็นชนิดที่การกลับมาของหรือเพราะมันเหมาะกับงบที่ใช้sq(x)
y
หากฉันเปลี่ยนรหัสอื่นซึ่งsq(x)
ไม่ได้ผลตอบแทนอีกต่อไปint
จะไม่แน่ใจจากบรรทัดนั้นเพียงอย่างเดียวว่าy
ควรปรับปรุงประเภทของ ตรงกันข้ามกับรหัสเดียวกัน แต่ใช้การอนุมานประเภท:
auto y = sq(x);
ในการนี้ความตั้งใจที่จะเป็นที่ชัดเจนจะต้องเป็นชนิดเดียวกันที่ส่งกลับโดยy
sq(x)
เมื่อรหัสเปลี่ยนประเภทการส่งคืนของsq(x)
ประเภทy
การเปลี่ยนแปลงจะจับคู่โดยอัตโนมัติ
ใน C ++ มีเหตุผลที่สองว่าทำไมตัวอย่างด้านบนนั้นง่ายกว่าด้วยการอนุมานประเภทการอนุมานประเภทไม่สามารถแนะนำการแปลงประเภทโดยนัย หากประเภทการกลับมาของsq(x)
ไม่ได้คอมไพเลอร์กับเงียบแทรกแปลงนัยไปint
int
หากชนิดส่งคืนของsq(x)
เป็นชนิดซับซ้อนชนิดที่กำหนดการoperator int()
เรียกใช้ฟังก์ชันที่ซ่อนอยู่นี้อาจซับซ้อนอย่างไม่มีกฎเกณฑ์