คำหลักอัตโนมัติ C ++ ทำไมมันมหัศจรรย์?


145

จากวัสดุทั้งหมดที่ฉันใช้ในการเรียนรู้ C ++ autoเป็นตัวระบุระยะเวลาเก็บข้อมูลแปลก ๆ ที่ไม่ได้มีจุดประสงค์เสมอ แต่เมื่อเร็ว ๆ นี้ฉันพบรหัสที่ใช้มันเป็นชื่อประเภทในและของตัวเอง ฉันลองมันด้วยความอยากรู้และมันจะเป็นประเภทของสิ่งที่ฉันจะกำหนดให้มัน!

ทันใดนั้นตัววนซ้ำ STL และอะไรก็ได้ที่ใช้แม่แบบนั้นเขียนได้ง่ายกว่า 10 เท่า รู้สึกเหมือนฉันกำลังใช้ภาษา 'สนุก' เช่น Python

คำหลักนี้อยู่ที่ไหนทั้งชีวิตของฉัน คุณจะรีบฝันของฉันโดยบอกว่ามันเป็นเอกสิทธิ์ของสตูดิโอภาพหรือไม่พกพา?


18
มันไม่ใช่. มายากล. มันเป็นเรื่องใหม่ ( โอ้วววมันแย่มาก ) ตอนนี้ async เป็นอนาคต ( หอบ )
sehe

2
นี่คือข้อมูลอ้างอิงเกี่ยวกับคำหลักอัตโนมัติen.cppreference.com/w/cpp/language/auto
andyqee

คำตอบ:


149

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

การใช้autoหมายถึงชนิดที่อนุมานได้เป็นของใหม่ด้วย C ++ 11

ในขณะเดียวกันก็auto x = initializerลดประเภทของประเภทxจากวิธีinitializerการเดียวกันกับที่การลดประเภทแม่แบบสำหรับเทมเพลตฟังก์ชัน พิจารณาเทมเพลตของฟังก์ชันดังนี้:

template<class T>
int whatever(T t) { 
    // point A
};

ณ จุด A, ประเภทที่ได้รับมอบหมายให้ขึ้นอยู่กับค่าผ่านสำหรับพารามิเตอร์T whateverเมื่อคุณทำเช่นauto x = initializer;นั้นการหักประเภทเดียวกันจะถูกใช้เพื่อกำหนดประเภทxของประเภทinitializerที่ใช้ในการเริ่มต้น

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

เมื่อคำตอบนี้ถูกเขียนขึ้นครั้งแรก (ในปี 2011 ก่อนที่หมึกจะแห้งบนมาตรฐาน C ++ 11) autoนั้นค่อนข้างพกพาอยู่แล้ว ทุกวันนี้มันสามารถพกพาได้อย่างทั่วถึงในคอมไพเลอร์หลัก เหตุผลที่ชัดเจนเพียงอย่างเดียวที่จะหลีกเลี่ยงก็คือถ้าคุณต้องการเขียนโค้ดที่เข้ากันได้กับคอมไพเลอร์ C หรือคุณมีความต้องการเฉพาะในการกำหนดเป้าหมายเฉพาะคอมไพเลอร์โพรงที่คุณรู้ว่าไม่รองรับ (เช่นบางคนยังเขียนโค้ด สำหรับ MS-DOS โดยใช้คอมไพเลอร์จาก Borland, Watcom และอื่น ๆ ที่ไม่ได้เห็นการอัพเกรดที่สำคัญในหลายทศวรรษ) หากคุณกำลังใช้คอมไพเลอร์กระแสหลักเวอร์ชันปัจจุบันอย่างสมเหตุสมผลแล้วก็ไม่มีเหตุผลใดที่จะหลีกเลี่ยงได้


24

เป็นเพียงการใช้คำหลักที่ไร้ประโยชน์โดยทั่วไปและมอบฟังก์ชันใหม่ที่ดีกว่า เป็นมาตรฐานใน C ++ 11 และคอมไพเลอร์ C ++ ส่วนใหญ่ที่มีแม้แต่ C ++ 11 รองรับก็รองรับ


Oh! อ๊ะไม่เคยนึกถึงภาษา C ++ ว่าเป็นสิ่งที่เปลี่ยนแปลงได้และในตัวของมันเอง ฉันจะต้องค้นหาสิ่งที่พวกเขาเพิ่มใน C ++ 11 นี้ฉันได้ยิน C ++ 0x นิดหน่อย แต่ไม่เคยขุดลึกเกินไป
Anne Quinn

7
@Clairvoire C ++ 0x เป็นชื่อระหว่างกาล เผยแพร่ในเดือนนี้และกลายเป็น C ++ 11
R. Martinho Fernandes

13

สำหรับตัวแปรระบุว่าประเภทของตัวแปรที่จะประกาศจะถูกหักโดยอัตโนมัติจาก initializer สำหรับฟังก์ชั่นระบุว่าประเภทการคืนสินค้าเป็นประเภทการส่งคืนตามมาหรือจะถูกหักจากคำสั่งการส่งคืน (ตั้งแต่ C ++ 14)

วากยสัมพันธ์

auto variable initializer   (1) (since C++11)

auto function -> return type    (2) (since C++11)

auto function   (3) (since C++14)

decltype(auto) variable initializer (4) (since C++14)

decltype(auto) function (5) (since C++14)

auto :: (6) (concepts TS)

cv(optional) auto ref(optional) parameter   (7) (since C++14)

คำอธิบาย

1) เมื่อประกาศตัวแปรในขอบเขตบล็อกในขอบเขตเนมสเปซในคำสั่งการเตรียมใช้งานของ for loops ฯลฯ อาจใช้คำหลักอัตโนมัติเป็นตัวระบุประเภท เมื่อกำหนดชนิดของ initializer แล้วคอมไพเลอร์จะกำหนดประเภทที่จะแทนที่คำหลักอัตโนมัติโดยใช้กฎสำหรับการลดอาร์กิวเมนต์เทมเพลตจากการเรียกใช้ฟังก์ชัน (ดูที่การลดอาร์กิวเมนต์เทมเพลต # บริบทอื่นสำหรับรายละเอียด) คำหลักอัตโนมัติอาจมาพร้อมกับตัวดัดแปลงเช่น const หรือ & ซึ่งจะมีส่วนร่วมในการลดประเภท ตัวอย่างเช่นที่กำหนดconst auto& i = expr;ประเภทของ i เป็นชนิดของอาร์กิวเมนต์ u ในแม่แบบจินตภาพtemplate<class U> void f(const U& u)หากการเรียกใช้ฟังก์ชันf(expr)ถูกรวบรวม ดังนั้น auto && อาจถูกอนุมานได้ว่าเป็นการอ้างอิงแบบ lvalue หรือการอ้างอิงแบบ rvalue ตาม initializer ซึ่งใช้ในช่วงที่ใช้สำหรับลูป หาก auto ถูกใช้เพื่อประกาศตัวแปรหลายชนิดประเภทที่อนุมานต้องตรงกัน ตัวอย่างเช่นการประกาศauto i = 0, d = 0.0;นั้นมีรูปแบบไม่ดีในขณะที่การประกาศauto i = 0, *p = &i;นั้นมีรูปแบบที่ถูกต้องและมีการสรุปอัตโนมัติเป็น int

2) ในการประกาศฟังก์ชั่นที่ใช้ไวยากรณ์ประเภทการส่งคืนต่อท้ายคำหลักอัตโนมัติไม่ทำการตรวจสอบประเภทอัตโนมัติ มันทำหน้าที่เป็นส่วนหนึ่งของไวยากรณ์

3) ในการประกาศฟังก์ชั่นที่ไม่ได้ใช้ไวยากรณ์ชนิดการส่งคืนต่อท้ายคีย์เวิร์ด auto ระบุว่าชนิดการส่งคืนจะถูกอนุมานจากตัวถูกดำเนินการของคำสั่งการส่งคืนโดยใช้กฎสำหรับการลดอาร์กิวเมนต์เทมเพลต

4) หากประเภทของตัวแปรที่ประกาศไว้คือ decltype (auto) คีย์เวิร์ด auto จะถูกแทนที่ด้วย expression (หรือรายการ expression) ของ initializer และประเภทที่เกิดขึ้นจริงจะถูกใช้โดยใช้กฎสำหรับ decltype

5) หากประเภทการคืนของฟังก์ชั่นมีการประกาศ decltype (อัตโนมัติ) คำหลักอัตโนมัติจะถูกแทนที่ด้วยตัวถูกดำเนินการของคำสั่งการส่งคืนและประเภทผลตอบแทนที่เกิดขึ้นจริงจะถูกหักโดยใช้กฎสำหรับ decltype

6) ตัวระบุชื่อที่ซ้อนกันของ form auto :: เป็นตัวยึดที่ถูกแทนที่ด้วยคลาสหรือประเภทการแจงนับตามกฎสำหรับการลดตัวยึดประเภทข้อ จำกัด

7) การประกาศพารามิเตอร์ในการแสดงออกแลมบ์ดา (ตั้งแต่ C ++ 14) การประกาศพารามิเตอร์ฟังก์ชัน (แนวคิด TS)

หมายเหตุ จนถึง C ++ 11 อัตโนมัติมีความหมายของตัวระบุระยะเวลาการจัดเก็บ การผสมตัวแปรและฟังก์ชั่นอัตโนมัติในการประกาศเดียวเนื่องจากauto f() -> int, i = 0;ไม่ได้รับอนุญาต

สำหรับข้อมูลเพิ่มเติม: http://en.cppreference.com/w/cpp/language/auto


11

ฟังก์ชั่นนี้ไม่ได้มีมาทั้งชีวิตของคุณ รองรับ Visual Studio ตั้งแต่ปี 2010 มันเป็นคุณสมบัติ C ++ 11 ใหม่ดังนั้นจึงไม่ใช่เอกสิทธิ์ของ Visual Studio และ / จะพกพาได้ คอมไพเลอร์ส่วนใหญ่รองรับแล้ว


3

มันไม่ได้ไปทุกที่ ... มันเป็นคุณสมบัติมาตรฐาน C ++ ใหม่ในการติดตั้ง C ++ 11 ที่ถูกกล่าวว่าในขณะที่มันเป็นเครื่องมือที่ยอดเยี่ยมสำหรับการทำให้การประกาศวัตถุง่ายขึ้นรวมถึงการทำความสะอาดไวยากรณ์สำหรับกระบวนทัศน์การโทรบางอย่าง (เช่น range-based for-loops) อย่าใช้มากเกินไป / ใช้ในทางที่ผิด :-)


3

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

มันมีประโยชน์มากเมื่อเราต้องใช้ตัววนซ้ำ ตัวอย่างเช่นสำหรับโค้ดด้านล่างเราสามารถใช้ "auto" แทนการเขียนไวยากรณ์ตัววนซ้ำทั้งหมด

int main() 
{ 

// Initialize set 
set<int> s; 

s.insert(1); 
s.insert(4); 
s.insert(2); 
s.insert(5); 
s.insert(3); 

// iterator pointing to 
// position where 2 is 
auto pos = s.find(3); 

// prints the set elements 
cout << "The set elements after 3 are: "; 
for (auto it = pos; it != s.end(); it++) 
    cout << *it << " "; 

return 0; 
}

นี่คือวิธีที่เราสามารถใช้คำหลัก "อัตโนมัติ"


0

It's Magic คือความสามารถในการลดการเขียนโค้ดสำหรับ Variable Type ทุกประเภทที่ส่งผ่านไปยังฟังก์ชั่นเฉพาะ พิจารณาฟังก์ชั่น Python ที่คล้ายกัน print () ในส่วนของ C base

#include <iostream>
#include <string>
#include <array>

using namespace std;

void print(auto arg) {
     cout<<arg<<" ";
}

int main()
{
  string f = "String";//tok assigned
  int x = 998;
  double a = 4.785;
  string b = "C++ Auto !";
//In an opt-code ASCII token stream would be iterated from tok's as:
  print(a);
  print(b);
  print(x);
  print(f);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.