มีเหตุผลใดที่ต้องใช้คีย์เวิร์ด 'auto' ใน C ++ 03?


85

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

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

ดังนั้นสิ่งนี้ทำให้ฉันมีคำหลักเพียงคำเดียวที่ฉัน (อาจ) ยังไม่เข้าใจทั้งหมด: autoคำหลัก มีความหมายอื่นนอกเหนือจาก 'ตัวแปรท้องถิ่นหรือไม่? สิ่งใดที่ไม่ได้ทำโดยปริยายสำหรับคุณทุกที่ที่คุณต้องการใช้? อย่างไรautoตัวแปรปฏิบัติตนในขอบเขตโปรแกรม? อะไรคือstatic autoตัวแปรในขอบเขตไฟล์? คำหลักนี้มีจุดประสงค์อื่นนอกเหนือจากที่มีอยู่เพื่อความสมบูรณ์หรือไม่?

คำตอบ:


74

autoเป็นอุปกรณ์เก็บข้อมูลระบุ, static, registerและexternมากเกินไป คุณสามารถใช้หนึ่งในสี่ข้อนี้ในการประกาศ

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

ฉันไม่รู้เหตุผลใด ๆ ที่จะใช้ใน C ++ ใน C เวอร์ชันเก่าที่มีกฎ int โดยนัยคุณสามารถใช้เพื่อประกาศตัวแปรเช่นใน:

int main(void) { auto i = 1; }

เพื่อทำให้เป็นไวยากรณ์ที่ถูกต้องหรือไม่คลุมเครือจากนิพจน์การกำหนดในกรณีที่iอยู่ในขอบเขต แต่ก็ใช้ไม่ได้ใน C ++ อยู่ดี (คุณต้องระบุประเภท) ตลกพอมาตรฐาน C ++ เขียน:

อ็อบเจ็กต์ที่ประกาศโดยไม่มี storage-class-specifier ที่ขอบเขตบล็อกหรือประกาศเป็นพารามิเตอร์ฟังก์ชันมีระยะเวลาการจัดเก็บอัตโนมัติตามค่าเริ่มต้น [หมายเหตุ: ด้วยเหตุนี้ตัวระบุอัตโนมัติจึงมักจะซ้ำซ้อนและไม่ได้ใช้บ่อยนัก การใช้อัตโนมัติอย่างหนึ่งคือการแยกแยะคำประกาศ - คำสั่งจากนิพจน์ - คำสั่ง (6.8) อย่างชัดเจน - หมายเหตุ]

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

int(a);

ด้วยความหมายใหม่ของการautoมาถึง C ++ 0x ฉันจะไม่แนะนำให้ใช้กับความหมายของ C ++ 03 ในรหัส


4
คอมไพเลอร์ C ++ มักใช้มี int โดยนัยสำหรับการส่งคืนค่าจากฟังก์ชันย้อนกลับไปใน ARM วันก่อนมาตรฐาน ... ก่อนจักรวรรดิ ...
Daniel Earwicker

1
ฉันเพิ่งจำได้ว่าเป็นวิธีคอมไพเลอร์ของฉันในการบอกว่าฉันลืมที่จะประกาศฟังก์ชันไปข้างหน้า มันจะบอกฉันว่าการใช้งานฟังก์ชั่นของฉันแตกต่างจากวิธีการประกาศเนื่องจากมี int โดยปริยาย
Carson Myers

29
ส่วนที่ดีที่สุดคือโปรแกรมเมอร์เคยเขียน "auto" (ตัวอักษรสี่ตัว) เพื่อช่วยตัวเองจากการเขียน "int" (ตัวอักษรสามตัว)
Max Lybbert

30
@ แม็กซ์ - เฮ้ผู้คนจำนวนมากพูดว่า "double-u-double-u-double-u" เป็นคำย่อของ "World Wide Web"
Daniel Earwicker

3
@smichak no, "volatile" เป็นตัวกำหนดประเภท แทนที่จะกำหนดตำแหน่งที่จะจัดเก็บค่าจะเปลี่ยนลักษณะการทำงานของการเขียนและอ่านจากออบเจ็กต์ของชนิดที่มีคุณสมบัติระเหยได้ อาจมีตัวแปรสแต็กที่มีคุณสมบัติที่เปลี่ยนแปลงได้ (คลาสหน่วยเก็บอัตโนมัติ) เช่นเดียวกับตัวแปรระยะเวลาการจัดเก็บแบบคงที่ที่มีคุณสมบัติเชิงระเหย (คลาสการจัดเก็บ 'คงที่' ในตัว, ตัวแปรที่ไม่ใช่โลคัล) นอกจากนั้นฉันไม่ทราบว่า "register volatile" เป็นชุดค่าผสมที่ถูกต้องหรือไม่ :)
Johannes Schaub - litb

86

ใน C ++ 11 autoมีความหมายใหม่: ช่วยให้คุณสามารถอนุมานประเภทของตัวแปรโดยอัตโนมัติ

ทำไมสิ่งนั้นถึงมีประโยชน์? ลองพิจารณาตัวอย่างพื้นฐาน:

std::list<int> a;
// fill in a
for (auto it = a.begin(); it != a.end(); ++it) {
  // Do stuff here
}

autoมีสร้าง iterator std::list<int>::iteratorประเภท

สิ่งนี้สามารถทำให้โค้ดที่ซับซ้อนอย่างจริงจังอ่านง่ายขึ้นมาก

ตัวอย่างอื่น:

int x, y;
auto f = [&]{ x += y; };
f();
f();

ที่นั่นautoอนุมานประเภทที่จำเป็นในการจัดเก็บนิพจน์แลมบ์ดาในตัวแปร Wikipedia มีความครอบคลุมที่ดีในเรื่องนี้


4
ยังไม่แน่ใจว่านี่เป็นการใช้งานอัตโนมัติที่ดีหรือไม่ โค้ดควรอ่านง่ายเขียนไม่ยาก!
DanDan

38
ฉันไม่รู้เกี่ยวกับคุณ แต่ฉันพบว่าสิ่งนี้อ่านง่ายกว่าสแปมประเภทตัววนซ้ำ
Overv

17
และถ้าสำหรับ reson zou บางตัวตัดสินใจที่จะเปลี่ยนคลาสจาก list <int> เป็น class อื่นคุณก็ไม่ต้องค้นหาการประกาศ iterator ทุกตัวและทำการเปลี่ยนแปลง
roslav

2
@KarateSnowMachine: ถ้าคุณต้องการ const คุณจะใช้ "const auto" แทน "auto"
darth happyface

4
@darth const auto it = a.begin();จะให้ const iteratorไม่ใช่ a const_iterator. คุณยังคงเปลี่ยนองค์ประกอบได้ แต่++itจะไม่สามารถรวบรวมได้ ในการรับ a const_iteratorคุณจะใช้auto it = a.cbegin();
fredoverflow

35

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

มีความหมายใหม่ล่าสุดใน C ++ 0x นั่นทำให้คุณมีความคิดว่ามันไร้ประโยชน์แค่ไหน!


1
โอ้มนุษย์ที่เคยไร้ประโยชน์ ฉันชอบความหมายใหม่ ทำให้โค้ดบางโค้ดมีรายละเอียดน้อยลงและซ้ำซ้อน
Carson Myers

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

7

GCC มีการใช้งานพิเศษautoสำหรับการทำงานที่ซ้อนกัน - ดูที่นี่

autoถ้าคุณมีฟังก์ชั่นที่ซ้อนกันที่คุณต้องการโทรสอบถามก่อนหมายของมันคุณจะต้องประกาศด้วย


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

3

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


1
ไม่แน่ - ถ้าคุณประกาศด้วย "register" คอมไพเลอร์จะไม่อนุญาตให้คุณใช้แอดเดรสของตัวดำเนินการ (& foo) กับตัวแปรเพราะมันไม่มีอยู่ที่ใดในหน่วยความจำ (และไม่มีที่อยู่)
Tim ถึง

3

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

auto unsigned int auiStack[1];   //variable must be on stack

จากนั้นฉันเข้าถึงนอกตัวแปร:

#define OFFSET_TO_RETURN_ADDRESS 8     //depends on compiler operation and current automatics
auiStack[OFFSET_TO_RETURN_ADDRESS] = alternate_return_address;

ดังนั้นautoคีย์เวิร์ดจึงช่วยบันทึกเจตนา


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

2

ตาม Stroustrup ใน "ภาษาการเขียนโปรแกรม C" (ฉบับที่ 4 ครอบคลุม C 11) การใช้ "อัตโนมัติ" มีสาเหตุหลัก ๆ ดังต่อไปนี้ (ส่วน 2.2.2) (มีการยกคำ Stroustrup):

1)

คำจำกัดความอยู่ในขอบเขตขนาดใหญ่ที่เราต้องการให้ผู้อ่านโค้ดของเรามองเห็นประเภทได้อย่างชัดเจน

ด้วย 'อัตโนมัติ' และตัวเริ่มต้นที่จำเป็นเราสามารถรู้ประเภทของตัวแปรได้ในพริบตา!

2)

เราต้องการให้ชัดเจนเกี่ยวกับช่วงหรือความแม่นยำของตัวแปร (เช่น double แทนที่จะเป็น float)

ในความคิดของฉันเป็นกรณีที่เหมาะกับที่นี่มีดังนี้:

   double square(double d)
    {
        return d*d; 
    }

    int square(int d)
    {
        return d*d; 
    }

    auto a1 = square(3);

    cout << a1 << endl;

    a1 = square(3.3);

    cout << a1 << endl;

3)

การใช้ "อัตโนมัติ" เราจะหลีกเลี่ยงความซ้ำซ้อนและการเขียนชื่อแบบยาว

ลองนึกภาพชื่อประเภทยาว ๆ จากตัววนซ้ำแบบเทมเพลต:

(รหัสจากส่วน 6.3.6.1)

template<class T> void f1(vector<T>& arg) {
    for (typename vector<T>::iterator p = arg.begin(); p != arg.end();   p)
        *p = 7;

    for (auto p = arg.begin(); p != arg.end();   p)
        *p = 7;
}

คะแนนเหล่านี้ใช้กับ C ++ 11 แต่ไม่ใช่กับ C ++ 03 การอนุมานประเภทเป็นสิ่งใหม่ใน C ++ 11
Jirka Hanika

1

ในคอมไพเลอร์แบบเก่า auto เป็นวิธีหนึ่งในการประกาศตัวแปรโลคัลเลย คุณไม่สามารถประกาศตัวแปรท้องถิ่นในคอมไพเลอร์เก่าเช่น Turbo C โดยไม่มีคำหลักอัตโนมัติ


ฉันกลัวว่าคุณจะเข้าใจผิด ไม่เคยมีข้อ จำกัด ใด ๆ แม้แต่ในรุ่นดั้งเดิมของ Turbo C ที่เรียกว่า Wizard-C ในปี 1986 หรือรุ่นใด ๆ ในรุ่น: MSC, Lattice C, Concurrent-C, High-C, Watcom-C ...
chqrlie

1

ความหมายใหม่ของคำสำคัญอัตโนมัติใน C ++ 0x ได้รับการอธิบายไว้อย่างดีโดย Stephan T. Lavavej ของ Microsoft ในการบรรยายวิดีโอที่สามารถดู / ดาวน์โหลดได้อย่างอิสระใน STL ซึ่งพบได้ที่ไซต์ Channel 9 ของ MSDN ที่นี่

การบรรยายควรค่าแก่การดูอย่างครบถ้วน แต่ส่วนที่เกี่ยวกับคำหลักอัตโนมัติอยู่ที่ประมาณนาทีที่ 29 (โดยประมาณ)


1

'auto' มีความหมายอื่นนอกเหนือจาก 'local variable หรือไม่?

ไม่อยู่ใน C ++ 03

สิ่งใดที่ไม่ได้ทำโดยปริยายสำหรับคุณทุกที่ที่คุณต้องการใช้?

ไม่มีอะไรเลยใน C ++ 03

ตัวแปรอัตโนมัติทำงานอย่างไรในขอบเขตโปรแกรม ตัวแปรอัตโนมัติคงที่ในขอบเขตไฟล์คืออะไร?

ไม่อนุญาตให้ใช้คำหลักภายนอกเนื้อหาของฟังก์ชัน / วิธีการ

คีย์เวิร์ดนี้มีวัตถุประสงค์ [ใน C ++ 03] นอกเหนือจากที่มีอยู่เพื่อความสมบูรณ์หรือไม่?

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

คีย์เวิร์ดนี้มีจุดประสงค์ใดใน C นอกเหนือจากที่มีอยู่เพื่อความสมบูรณ์หรือไม่?

ฉันเพิ่งเรียนรู้เมื่อไม่นานมานี้: ความสะดวกในการย้ายโปรแกรมโบราณจาก B C พัฒนามาจากภาษาที่เรียกว่า B ซึ่งไวยากรณ์ค่อนข้างคล้ายกับภาษา C อย่างไรก็ตาม B ไม่มีประเภทใดเลย วิธีเดียวในการประกาศตัวแปรใน B คือการระบุประเภทการจัดเก็บ ( autoหรือextern) แบบนี้:

อัตโนมัติฉัน;

ไวยากรณ์นี้ยังคงทำงานใน C และเทียบเท่ากับ

int ฉัน;

เพราะใน C, ค่าเริ่มต้นของระดับการจัดเก็บและค่าเริ่มต้นประเภทที่จะauto intฉันเดาว่าทุกโปรแกรมที่มาใน B และถูกย้ายไปยัง C นั้นเต็มไปด้วยautoตัวแปรอย่างแท้จริงในเวลานั้น

C ++ 03 ไม่อนุญาตให้ใช้สไตล์ C โดยนัย int อีกต่อไป แต่ยังคงรักษาautoคีย์เวิร์ดที่ไม่เป็นประโยชน์อีกต่อไปเนื่องจากไม่เหมือนกับ int โดยนัยซึ่งไม่ทราบว่าก่อให้เกิดปัญหาใด ๆ ในไวยากรณ์ของ C

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