แบบฟอร์มไม่ถูกต้อง:
int &z = 12;
แบบฟอร์มที่ถูกต้อง:
int y;
int &r = y;
คำถาม :
ทำไมรหัสแรกผิด? "ความหมาย " ของข้อผิดพลาดในชื่อเรื่องคืออะไร?
แบบฟอร์มไม่ถูกต้อง:
int &z = 12;
แบบฟอร์มที่ถูกต้อง:
int y;
int &r = y;
คำถาม :
ทำไมรหัสแรกผิด? "ความหมาย " ของข้อผิดพลาดในชื่อเรื่องคืออะไร?
(ostringstream() << "x=" << x).str()
คำตอบ:
C ++ 03 3.10 / 1 พูดว่า: "ทุกนิพจน์เป็น lvalue หรือ rvalue" สิ่งสำคัญคือต้องจำไว้ว่าค่า lvalueness เทียบกับ rvalueness เป็นคุณสมบัติของการแสดงออกไม่ใช่ของวัตถุ
Lvalues ออบเจ็กต์ชื่อที่คงอยู่นอกเหนือจากนิพจน์เดียว ตัวอย่างเช่นobj
, *ptr
, ptr[index]
และ++x
เป็น lvalues ทั้งหมด
Rvalues คือชั่วคราวที่ระเหยเมื่อสิ้นสุดนิพจน์เต็มที่พวกมันมีชีวิตอยู่ ("ที่อัฒภาค") ตัวอย่างเช่น1729
, x + y
, std::string("meow")
และx++
มี rvalues ทั้งหมด
แอดเดรส - ของโอเปอเรเตอร์กำหนดให้ "ตัวถูกดำเนินการต้องเป็นค่า lvalue" ถ้าเราสามารถใช้แอดเดรสของนิพจน์หนึ่งนิพจน์นั้นคือ lvalue มิฉะนั้นจะเป็น rvalue
&obj; // valid
&12; //invalid
int & = 12;
นิพจน์จึงไม่ถูกต้องมาตรฐานกล่าวว่าลิเทอรัลของสตริงเป็นค่า lvalue ตัวอักษรอื่น ๆ เป็นค่า rvalues
std::string("meow")
สร้างออบเจ็กต์ประเภทstd::string
และให้ค่า r ที่กำหนดอ็อบเจ็กต์1729
นี้ไม่มีผลข้างเคียงและให้ค่า 1729 เป็น rvalue int
ของพิมพ์
"Lvalues name objects that persist beyond a single expression."
นี้เป็นคำสั่งที่ถูกต้อง 100% ในทางกลับกันตัวอย่างของคุณ(const int &)1
ไม่ถูกต้องเนื่องจากไม่ใช่วัตถุ "ชื่อ"
int &z = 12;
ทางด้านขวามืออ็อบเจ็กต์ชั่วคราวประเภทint
ถูกสร้างขึ้นจากอินทิกรัลลิเทอรั12
ล แต่ชั่วคราวไม่สามารถถูกผูกไว้กับการอ้างอิงที่ไม่ใช่ const ดังนั้นข้อผิดพลาด เหมือนกับ:
int &z = int(12); //still same error
เหตุใดจึงมีการสร้างชั่วคราว เนื่องจากการอ้างอิงต้องอ้างถึงอ็อบเจ็กต์ในหน่วยความจำและสำหรับอ็อบเจ็กต์ที่มีอยู่นั้นจะต้องถูกสร้างขึ้นก่อน เนื่องจากวัตถุไม่มีชื่อจึงเป็นวัตถุชั่วคราว มันไม่มีชื่อ จากคำอธิบายนี้มันค่อนข้างชัดเจนว่าทำไมกรณีที่สองถึงใช้ได้
วัตถุชั่วคราวสามารถถูกผูกไว้กับการอ้างอิง const ซึ่งหมายความว่าคุณสามารถทำได้:
const int &z = 12; //ok
เพื่อความสมบูรณ์ฉันต้องการเพิ่มเติมว่า C ++ 11 ได้แนะนำ rvalue-reference ซึ่งสามารถผูกกับวัตถุชั่วคราวได้ ดังนั้นใน C ++ 11 คุณสามารถเขียนสิ่งนี้:
int && z = 12; //C+11 only
โปรดทราบว่ามี&&
intead ของ&
. นอกจากนี้โปรดทราบว่าconst
ไม่จำเป็นอีกต่อไปแม้ว่าออบเจ็กต์ที่z
ผูกกับเป็นอ็อบเจ็กต์ชั่วคราวที่สร้างขึ้นจากอินทิกรัล - ลิเทอรั12
ล
ตั้งแต่ C ++ 11 ได้แนะนำrvalue อ้างอิง , int&
นี้เรียกว่าต่อจากนี้ไปlvalue อ้างอิง
12
int&
เป็นค่าคงที่รวบรวมเวลาที่ไม่สามารถเปลี่ยนแปลงได้แตกต่างจากข้อมูลอ้างอิงจาก สิ่งที่คุณสามารถทำได้คือ
const int& z = 12;
void f( vector<int> const & )
ซึ่งเป็นสำนวนที่จะส่งผ่านเวกเตอร์ที่ไม่ต้องแก้ไข ปัญหาตอนนี้คือf( vector<int>(5) )
จะไม่ถูกต้องและผู้ใช้จะต้องจัดเตรียมโอเวอร์โหลดที่แตกต่างออกvoid f( vector<int> v ) { f(v); }
ไป
f( vector<int>(5) )
คอมไพลเลอร์จะสร้างชั่วคราวจากนั้นเชื่อมโยงการอ้างอิงกับชั่วคราวนั้นและในทำนองเดียวกัน หากมีการแปลงโดยนัยจาก5
โดยตรง สิ่งนี้ช่วยให้คอมไพลเลอร์สร้างลายเซ็นเดียวสำหรับฟังก์ชันและเปิดใช้งานฟังก์ชันผู้ใช้คนเดียว จากนั้นจะมีการกำหนดพฤติกรรมที่คล้ายกันสำหรับการใช้การอ้างอิงคงที่เพื่อความสอดคล้อง
T const & r = *ptr;
การใช้r
ฟังก์ชันใด ๆ ในภายหลังสามารถแทนที่ได้*ptr
และr
ไม่จำเป็นต้องมีอยู่ในรันไทม์) หรืออาจต้องใช้งานโดยเก็บที่อยู่ของวัตถุที่เป็นนามแฝง (พิจารณาจัดเก็บข้อมูลอ้างอิงในฐานะสมาชิกของวัตถุ) ซึ่งใช้เป็นตัวชี้การอ้างอิงอัตโนมัติ
นี่คือกฎของภาษา C ++:
12
) คือ "rvalue"int &ri = 12;
เป็นรูปแบบที่ไม่ถูกต้องคุณต้องเข้าใจว่านี่คือกฎ C ++ พวกเขาเป็นเพียง
เป็นเรื่องง่ายที่จะประดิษฐ์ภาษาอื่นพูดว่า C ++ 'โดยมีกฎที่แตกต่างกันเล็กน้อย ใน C ++ 'จะได้รับอนุญาตให้สร้างการอ้างอิงที่ไม่ใช่ const ด้วย rvalue ไม่มีอะไรที่ไม่สอดคล้องกันหรือเป็นไปไม่ได้ที่นี่
แต่จะอนุญาตให้มีโค้ดที่มีความเสี่ยงซึ่งโปรแกรมเมอร์อาจไม่ได้รับสิ่งที่เขาตั้งใจไว้และนักออกแบบ C ++ ก็ตัดสินใจอย่างถูกต้องที่จะหลีกเลี่ยงความเสี่ยงนั้น
การอ้างอิงคือ "ตัวชี้ที่ซ่อนอยู่" (ไม่ใช่ค่าว่าง) สำหรับสิ่งที่เปลี่ยนแปลงได้ (ค่า lvalues) คุณไม่สามารถกำหนดให้เป็นค่าคงที่ มันควรจะเป็น "ตัวแปร"
แก้ไข ::
ฉันกำลังคิดถึง
int &x = y;
เกือบจะเทียบเท่ากับ
int* __px = &y;
#define x (*__px)
__px
ชื่อใหม่อยู่ที่ไหนและ#define x
ผลงานเฉพาะในบล็อกที่มีการประกาศx
การอ้างอิง
const
:)
const