คำถามนี้ไม่สามารถตอบได้อย่างสมบูรณ์ในรหัส คุณอาจจะสามารถเขียนรหัส "เทียบเท่า" ได้บ้าง แต่ไม่ได้ระบุมาตรฐานดังกล่าว
เมื่อออกนอกเส้นทางมา[expr.prim.lambda]เริ่มกันเลย สิ่งแรกที่ควรทราบคือตัวสร้างจะกล่าวถึงเฉพาะใน[expr.prim.lambda.closure]/13:
  ประเภทการปิดที่สัมพันธ์กับlambda-expressionไม่มี constructor เริ่มต้นหากlambda-expressionมีlambda-captureและ default constructor เริ่มต้นเป็นอย่างอื่น มันมีตัวสร้างการคัดลอกเริ่มต้นและตัวสร้างการย้ายเริ่มต้น ([class.copy.ctor]) มีตัวดำเนินการกำหนดค่าการคัดลอกที่ถูกลบหากlambda-expressionมีlambda-captureและตัวดำเนินการคัดลอกและย้ายที่เป็นค่าเริ่มต้นเป็นอย่างอื่น ([class.copy.assign]) [ หมายเหตุ:ฟังก์ชั่นสมาชิกพิเศษเหล่านี้มีการกำหนดโดยนัยตามปกติและอาจถูกกำหนดเป็นลบ - บันทึกท้าย ]
ดังนั้นทันทีที่ค้างคาวควรมีความชัดเจนว่าคอนสตรัคเตอร์ไม่ได้เป็นทางการตามที่กำหนดไว้ในการถ่ายภาพวัตถุ คุณสามารถเข้าใกล้ได้ (ดูคำตอบ cppinsights.io) แต่รายละเอียดแตกต่างกัน (โปรดสังเกตว่ารหัสในคำตอบนั้นสำหรับกรณีที่ 4 ไม่ได้รวบรวม)
นี่เป็นมาตราฐานหลักที่จำเป็นในการหารือกรณีที่ 1:
[expr.prim.lambda.capture]/10
  [... ] 
  สำหรับแต่ละเอนทิตีที่บันทึกโดยการคัดลอกสมาชิกข้อมูลที่ไม่คงที่ที่ไม่มีชื่อจะถูกประกาศในประเภทการปิด คำสั่งประกาศของสมาชิกเหล่านี้ไม่ได้ระบุไว้ ประเภทของสมาชิกข้อมูลดังกล่าวเป็นประเภทอ้างอิงถ้ากิจการเป็นการอ้างอิงไปยังวัตถุการอ้างอิง lvalue ไปยังประเภทฟังก์ชั่นอ้างอิงถ้ากิจการเป็นการอ้างอิงไปยังฟังก์ชั่นหรือประเภทของกิจการที่ถูกจับที่สอดคล้องกันเป็นอย่างอื่น สมาชิกของสหภาพที่ไม่ระบุชื่อจะไม่ถูกคัดลอก
[expr.prim.lambda.capture]/11
  idทุกนิพจน์ภายในคำสั่งผสมของแลมบ์ดา - นิพจน์ที่เป็นการใช้ประโยชน์จากเอนทิตีที่ดักจับโดยการคัดลอกจะถูกแปลงเป็นการเข้าถึงสมาชิกข้อมูลที่ไม่มีชื่อที่สอดคล้องกันของประเภทการปิด [ ... ]
[expr.prim.lambda.capture]/15
  เมื่อประเมินแลมบ์ดานิพจน์เอนทิตีที่ถูกจับโดยการคัดลอกจะถูกใช้เพื่อกำหนดค่าเริ่มต้นให้กับสมาชิกข้อมูลที่ไม่คงที่ที่สอดคล้องกันของวัตถุปิดที่เกิดขึ้นและสมาชิกข้อมูลที่ไม่คงที่ที่สอดคล้องกับการเริ่มต้น ระบุโดย initializer ที่สอดคล้องกัน (ซึ่งอาจเป็นการคัดลอกหรือการกำหนดค่าเริ่มต้นโดยตรง) [ ... ]
ลองนำสิ่งนี้ไปใช้กับกรณีของคุณ 1:
  กรณีที่ 1: การดักจับตามค่า / การดักจับเริ่มต้นตามค่า
int x = 6;
auto lambda = [x]() { std::cout << x << std::endl; };
ประเภทปิดแลมบ์ดานี้จะมีชื่อไม่คงที่ข้อมูลสมาชิก (ขอเรียกว่า__x) ประเภทint(ตั้งแต่xจะไม่อ้างอิงหรือฟังก์ชั่น) และการเข้าถึงภายในร่างกายแลมบ์ดาจะเปลี่ยนการเข้าถึงx __xเมื่อเราประเมินการแสดงออกแลมบ์ดา (เช่นเมื่อกำหนดไปlambda) เราโดยตรงการเริ่มต้น ด้วย__xx
กล่าวโดยย่อจะมีเพียงหนึ่งสำเนาเท่านั้น Constructor ของประเภทการปิดไม่เกี่ยวข้องและเป็นไปไม่ได้ที่จะแสดงสิ่งนี้ใน "ปกติ" C ++ (โปรดทราบว่าประเภทการปิดไม่ได้เป็นประเภทรวม )
การอ้างอิงที่เกี่ยวข้องกับ[expr.prim.lambda.capture]/12:
  เอนทิตีถูกจับโดยการอ้างอิงถ้ามันถูกจับโดยปริยายหรืออย่างชัดเจน แต่ไม่ถูกจับโดยการคัดลอก มันไม่ได้ระบุว่าสมาชิกข้อมูลที่ไม่คงที่ไม่มีชื่อเพิ่มเติมจะประกาศในประเภทการปิดสำหรับหน่วยงานที่บันทึกโดยอ้างอิง [ ... ]
มีอีกย่อหน้าเกี่ยวกับการอ้างอิงการอ้างอิง แต่เราไม่ได้ทำอย่างนั้น
ดังนั้นสำหรับกรณีที่ 2:
  กรณีที่ 2: การดักจับโดยการอ้างอิง / การดักจับเริ่มต้นโดยการอ้างอิง
int x = 6;
auto lambda = [&x]() { std::cout << x << std::endl; };
เราไม่ทราบว่ามีการเพิ่มสมาชิกประเภทการปิดหรือไม่ xในร่างกายแลมบ์ดาอาจจะหมายถึงxภายนอกโดยตรง นี่ขึ้นอยู่กับคอมไพเลอร์เพื่อคิดออกและมันจะทำในภาษากลางบางรูปแบบ (ซึ่งแตกต่างจากคอมไพเลอร์เป็นคอมไพเลอร์) ไม่ใช่การแปลงซอร์สของรหัส C ++
เริ่มการดักจับมีรายละเอียดใน[expr.prim.lambda.capture]/6:
  การเริ่มต้นการจับภาพจะทำงานราวกับว่ามันประกาศและจับตัวแปรของรูปแบบauto init-capture ;ที่มีภูมิภาคการประกาศเป็นคำสั่งผสมของแลมบ์ดานิพจน์ยกเว้นว่า:
  
  
  - (6.1) หากการจับภาพเกิดจากการคัดลอก (ดูด้านล่าง) สมาชิกข้อมูลที่ไม่คงที่ที่ประกาศไว้สำหรับการดักจับและตัวแปรจะถือว่าเป็นสองวิธีที่แตกต่างกันในการอ้างถึงวัตถุเดียวกันซึ่งมีอายุการใช้งานของข้อมูลไม่คงที่ สมาชิกและไม่มีการคัดลอกและทำลายเพิ่มเติมและ
 
  - (6.2) หากการดักจับเป็นการอ้างอิงอายุการใช้งานของตัวแปรจะสิ้นสุดลงเมื่ออายุการใช้งานของวัตถุปิดสิ้นสุดลง
 
  
ให้ดูที่กรณีที่ 3:
  กรณีที่ 3: การจับภาพเริ่มต้นทั่วไป
auto lambda = [x = 33]() { std::cout << x << std::endl; };
ตามที่ระบุไว้ลองจินตนาการว่านี่เป็นตัวแปรที่ถูกสร้างขึ้นauto x = 33;และคัดลอกโดยชัดเจน ตัวแปรนี้เป็นเพียง "มองเห็นได้" ภายในร่างกายแลมบ์ดา ดังที่กล่าวไว้[expr.prim.lambda.capture]/15ก่อนหน้านี้การกำหนดค่าเริ่มต้นของสมาชิกประเภทปิด ( __xสำหรับลูกหลาน) ที่สอดคล้องกันนั้นเริ่มต้นจากการประเมินค่าของการแสดงออกแลมบ์ดา
สำหรับการหลีกเลี่ยงข้อสงสัย: นี่ไม่ได้หมายความว่าจะมีการเตรียมใช้งานสองครั้งที่นี่ auto x = 33;เป็น "ราวกับว่า" จะได้รับมรดกความหมายของการจับภาพที่เรียบง่ายและการเริ่มต้นอธิบายคือการปรับเปลี่ยนความหมายเหล่านั้น การเริ่มต้นเพียงครั้งเดียวเกิดขึ้น
นอกจากนี้ยังครอบคลุมถึงกรณีที่ 4:
auto l = [p = std::move(unique_ptr_var)]() {
  // do something with unique_ptr_var
};
สมาชิกประเภทการปิดจะเริ่มต้นได้โดย__p = std::move(unique_ptr_var)เมื่อมีการประเมินการแสดงออกของแลมบ์ดา (เช่นเมื่อlถูกกำหนดให้) การเข้าถึงในร่างกายแลมบ์ดาจะกลายเป็นเข้าถึงp__p
TL; DR: เฉพาะการคัดลอก / การกำหนดค่าเริ่มต้น / การเคลื่อนย้ายที่น้อยที่สุดเท่านั้นที่ทำได้ (ดังที่คาดหวัง / คาดหวัง) ฉันจะสมมติว่า lambdas ไม่ได้ระบุไว้ในแง่ของการแปลงแหล่งที่มา (ต่างจากน้ำตาล syntactic อื่น ๆ ) อย่างแน่นอนเพราะการแสดงสิ่งต่าง ๆ ในแง่ของการก่อสร้างจะทำให้การดำเนินการฟุ่มเฟือย
ฉันหวังว่าสิ่งนี้จะทำให้เกิดความกลัวในคำถาม :)