ทำไม int x {y = 5} จึงเป็นไปได้


10
int main() {
    int y;
    int x{ y = 5 };
    //x is 5
}

สิ่งนี้เป็นไปได้อย่างไรเนื่องจาก y = 5 ไม่ใช่นิพจน์ที่คำนวณได้?

นอกจากนี้ทำไมคอมไพเลอร์หรือ IDE ไม่บ่นเกี่ยวกับ main () ไม่ส่งคืน int


8
y = 5 คือ5การแสดงออกและมีความคุ้มค่า ทำไมคุณคิดว่ามันไม่ใช่
ไร้ประโยชน์

2
เกี่ยวกับการขาดหายไปreturnของmainดูคำถามนี้
วอลนัท

3
ดีกว่าให้นำคำถามที่สองออก หนึ่งเดียวคำถามต่อคำถามเป็นรุ่นที่แนะนำในกองมากเกิน
StoryTeller - Unslander Monica

บางทีคุณควรกำหนดคำถามใหม่ว่าทำไมy = 5ให้ผลตอบแทน 5 ตรงนี้ ความเป็นไปได้ของผู้ประกอบการที่ได้รับมอบหมายเพื่อส่งคืนบางสิ่งเป็นคุณสมบัติที่แปลกประหลาดของ C / C ++
user7860670

คำตอบ:


11

ฉันจะเริ่มจากคำถามสุดท้ายของคุณ

นอกจากนี้ทำไมคอมไพเลอร์หรือ IDE ไม่บ่นเกี่ยวกับ main () ไม่ส่งคืน int

ตามมาตรฐาน C ++ (ฟังก์ชั่นหลัก 6.6.1)

5 คำสั่ง return ใน main มีผลต่อการออกจากฟังก์ชั่นหลัก (ทำลายวัตถุใด ๆ ที่มีระยะเวลาการเก็บข้อมูลอัตโนมัติ) และการเรียก std :: exit พร้อมกับค่า return เป็นอาร์กิวเมนต์ หากการควบคุมไหลออกจากจุดสิ้นสุดของคำสั่งผสมของหลักผลจะเท่ากับผลตอบแทนกับตัวถูกดำเนินการ 0 (ดูเพิ่มเติมที่ 18.3)

และสัมพันธ์กับคำถามนี้

สิ่งนี้เป็นไปได้อย่างไรเนื่องจาก y = 5 ไม่ใช่นิพจน์ที่คำนวณได้?

จากมาตรฐาน C ++ (8.18 การกำหนดและตัวดำเนินการกำหนดผสม)

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

ประกาศนี้

int x{ y = 5 };

สามารถแบ่งเท่า ๆ กันเป็นสองงบ

y = 5;
int x{ y };

ยิ่งไปกว่านั้นใน C ++ คุณสามารถอ้างอิงถึงตัวแปร y ได้ด้วยวิธีต่อไปนี้

int &x{ y = 5 };

นี่คือโปรแกรมสาธิต

#include <iostream>

int main() 
{
    int y;
    int &x{ y = 5 };    

    std::cout << "y = " << y << '\n';

    x = 10;

    std::cout << "y = " << y << '\n';
}

เอาท์พุทมันคือ

y = 5
y = 10

คุณสามารถประกาศนี้

int x{ y = 5 };

เขียนเหมือนกัน

int x = { y = 5 };

อย่างไรก็ตามให้คำนึงว่ามีความแตกต่างระหว่างสองสิ่งนี้ (ดูคล้าย ๆ กับการประกาศข้างต้น) สองการประกาศ

auto x{ y = 5 };

และ

auto x = { y = 5 };

ในการประกาศครั้งแรกตัวแปรที่มีชนิดx intในการประกาศสองตัวแปรที่มีชนิดxstd::initializer_list<int>

เพื่อให้เห็นความแตกต่างได้ชัดเจนยิ่งขึ้นดูว่าค่าของวัตถุนั้นถูกส่งออกอย่างไร

#include <iostream>

int main() 
{
    int y;
    auto x1 { y = 5 };  

    std::cout << "x1 = " << x1 << '\n';

    auto x2 = { y = 10 };   

    std::cout << "*x2.begin()= " << *x2.begin() << '\n';

    std::cout << "y = " << y << '\n';

    return 0;
}

ผลลัพธ์ของโปรแกรมคือ

x1 = 5
*x2.begin()= 10
y = 10

16

สิ่งนี้เป็นไปได้อย่างไรเนื่องจาก y = 5 ไม่ใช่นิพจน์ที่คำนวณได้?

มันเป็นงานและได้รับมอบหมายให้ผลผลิตค่าคือ "พิมพ์ CV-ไม่มีเงื่อนไขของตัวถูกดำเนินการทางด้านซ้าย" ดู[expr.ass / 3] ดังนั้นy = 5จะส่งผลในyซึ่งเป็นที่ใช้ในการเริ่มต้น5x

สำหรับคำถามที่สองของคุณโปรดดู cppreference ในmain (หรือ[basic.start.main / 5] ):

ร่างกายของฟังก์ชั่นหลักไม่จำเป็นต้องมีreturnคำสั่งถ้าควบคุมถึงจุดสิ้นสุดของหลักโดยไม่ต้องเผชิญหน้ากับคำสั่งผลที่ออกมาก็คือว่าในการดำเนินการreturnreturn 0;

ดังนั้นคอมไพเลอร์หรือ IDE เตือนคุณเกี่ยวกับreturnคำสั่งที่ขาดหายไปในตอนท้ายของmainจะผิดธรรมดา ยอมรับความจริงที่ว่าคุณควรreturnวัตถุจากที่ไม่ใช่voidหน้าที่execptmainเป็นชนิดของ ... ดีด้วยเหตุผลทางประวัติศาสตร์ฉันเดา


2
การแสดงออกสามารถส่งผลในค่า แต่เพียงฟังก์ชั่นreturnหนึ่ง -pedantic
ไร้ประโยชน์เมื่อ

ฉันคิดว่านี่คือ x {y = 5}; คำสั่งไม่ถูกต้องใน c
bhura

@bhura - คำถามเกี่ยวกับ C ++ ไม่ใช่ C
StoryTeller - Unslander Monica

อาจจะคุ้มค่าที่จะกล่าวถึงแม้ว่าไม่จำเป็นต้องใช้ แต่การคืนค่าจากหลักมักถือเป็นการปฏิบัติที่ดี?
Aconcagua

4

operator=()ส่งผลให้ค่าซึ่งเป็นค่าที่กำหนดให้กับตัวแปร ด้วยเหตุนี้จึงเป็นไปได้ที่การมอบหมายลูกโซ่เช่นนี้:

int x, y, z;
x = y = z = 1;

แสดงออกได้รับมอบหมายมีความคุ้มค่า ฟังก์ชั่นมีค่าตอบแทน การแสดงออกไม่ได้
Pete Becker

3

หากคุณดูที่เอกสารเกี่ยวกับ cppreferenceคุณจะเห็นว่าoperator=()ส่งคืนการอ้างอิงไปยังวัตถุที่ได้รับมอบหมาย ดังนั้นการมอบหมายสามารถใช้เป็นนิพจน์ที่ส่งคืนวัตถุที่ได้รับมอบหมาย

จากนั้นเป็นเพียงการมอบหมายตามปกติพร้อมกับเครื่องมือจัดฟัน

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