วิธีการส่งผ่านวัตถุไปยังฟังก์ชั่นใน C ++?


249

ฉันใหม่สำหรับการเขียนโปรแกรม C ++ แต่ฉันมีประสบการณ์ใน Java ฉันต้องการคำแนะนำเกี่ยวกับวิธีการส่งวัตถุไปยังฟังก์ชั่นใน C ++

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

มันจะดีถ้าคุณสามารถอธิบายได้ว่าจะใช้ตัวเลือกเหล่านั้นด้วยที่ไหน


6
คุณกำลังเรียนหนังสือ C ++ จากอะไร

17
ไม่แนะนำให้ใช้หนังสือเล่มนั้น ไปสำหรับ C ++ Primer โดย Stan Lippman
Prasoon Saurav

23
มีปัญหาของคุณคือ Schildt เป็น cr * p - รับตัวเร่งความเร็ว C + + โดย Koenig & Moo

9
ฉันสงสัยว่าไม่มีใครพูดถึงภาษา C ++ Programming โดย Bjarne Stroustrup Bjarne Stroustrup เป็นผู้สร้าง C ++ หนังสือที่ดีมากสำหรับการเรียนรู้ C ++
จอร์จ

15
@ George: TC ++ PL ไม่ได้มีไว้สำหรับผู้เริ่มต้น แต่ก็ถือว่าเป็นพระคัมภีร์สำหรับ C ++ xD
Prasoon Saurav

คำตอบ:


277

กฎง่ายๆสำหรับC ++ 11:

ผ่านค่ายกเว้นเมื่อ

  1. คุณไม่จำเป็นต้องเป็นเจ้าของของวัตถุและนามแฝงง่ายจะทำในกรณีที่คุณผ่านconstการอ้างอิง ,
  2. คุณต้องกลายพันธุ์วัตถุซึ่งในกรณีที่ใช้ผ่านโดยไม่constอ้างอิง lvalue ,
  3. คุณผ่านวัตถุของชั้นเรียนมาเป็นฐานเรียนซึ่งในกรณีที่คุณต้องผ่านการอ้างอิง (ใช้กฎก่อนหน้านี้เพื่อพิจารณาว่าจะส่งต่อโดยconstอ้างอิงหรือไม่)

ไม่แนะนำให้ส่งผ่านตัวชี้ พารามิเตอร์เผื่อเลือกแสดงได้ดีที่สุดว่าเป็นstd::optional( boost::optionalสำหรับ std libs ที่เก่ากว่า) และการทำ aliasing นั้นทำได้ดีโดยการอ้างอิง

ความหมายของการย้าย C ++ 11 ทำให้การส่งผ่านและการกลับมาตามค่าน่าสนใจยิ่งขึ้นแม้กับวัตถุที่ซับซ้อน


กฎง่ายๆสำหรับC ++ 03:

ส่งผ่านข้อโต้แย้งโดยconstการอ้างอิงยกเว้นเมื่อ

  1. พวกเขาจะต้องมีการเปลี่ยนแปลงภายในฟังก์ชั่นและการเปลี่ยนแปลงดังกล่าวควรจะสะท้อนออกไปข้างนอกซึ่งในกรณีที่คุณผ่านโดยไม่constอ้างอิง
  2. ฟังก์ชั่นควรจะเรียกได้โดยไม่มีข้อโต้แย้งใด ๆ ในกรณีนี้คุณจะผ่านตัวชี้เพื่อให้ผู้ใช้สามารถผ่านNULL/ 0/ nullptrแทน ใช้กฎก่อนหน้านี้เพื่อตรวจสอบว่าคุณควรผ่านตัวชี้ไปยังconstอาร์กิวเมนต์
  3. เป็นชนิดในตัวซึ่งสามารถคัดลอกได้
  4. พวกเขาจะต้องเปลี่ยนภายในฟังก์ชั่นและการเปลี่ยนแปลงดังกล่าวไม่ควรสะท้อนนอกซึ่งในกรณีที่คุณสามารถส่งโดยการคัดลอก (ทางเลือกจะผ่านตามกฎก่อนหน้าและทำสำเนาภายในฟังก์ชั่น)

(ที่นี่ "pass by value" เรียกว่า "pass by copy" เนื่องจากการส่งค่าตามค่าจะสร้างสำเนาใน C ++ 03 เสมอ)


มีมากกว่านี้ แต่กฎของผู้เริ่มต้นไม่กี่คนเหล่านี้จะทำให้คุณค่อนข้างไกล


17
+1 - ฉันจะทราบด้วยว่าบางคน (เช่น Google) รู้สึกว่าวัตถุที่จะเปลี่ยนภายในฟังก์ชั่นควรส่งผ่านตัวชี้แทนการอ้างอิงที่ไม่ใช่แบบคอน การให้เหตุผลว่าเมื่อที่อยู่ของวัตถุถูกส่งผ่านไปยังฟังก์ชั่นจะมีความชัดเจนมากขึ้นว่าฟังก์ชั่นดังกล่าวอาจมีการเปลี่ยนแปลง ตัวอย่าง: ด้วยการอ้างอิงการโทรคือ foo (แถบ); ไม่ว่าการอ้างอิงจะเป็น const หรือไม่พร้อมกับตัวชี้มันคือ foo (& bar); และเห็นได้ชัดว่า foo กำลังถูกส่งผ่านวัตถุที่เปลี่ยนแปลงได้
RC

19
@RC ยังไม่บอกคุณว่าตัวชี้เป็น const หรือไม่ หลักเกณฑ์ของ Google ได้เกิดขึ้นมากมายในชุมชนออนไลน์ C ++ ที่หลากหลาย IMHO

14
ในขณะที่ในบริบทอื่น ๆ ของ Google อาจเป็นผู้นำใน C ++ คู่มือสไตล์ของพวกเขาไม่ค่อยดีนัก
David Rodríguez - dribeas

4
@ArunSaha: ในฐานะที่เป็นไกด์สไตล์บริสุทธิ์ Stroustrup มีไกด์ที่พัฒนาขึ้นสำหรับ บริษัท การบินและอวกาศ ฉันเรียกดูผ่านคู่มือ Google และไม่ชอบด้วยเหตุผลสองสามข้อ ซัทเทอและ Alexandrescu c ++ มาตรฐานการเข้ารหัสเป็นหนังสือที่ดีในการอ่านและคุณจะได้รับค่อนข้างน้อยของคำแนะนำที่ดี แต่มันไม่ได้จริงๆคู่มือสไตล์ ฉันไม่รู้ตัวตรวจสอบอัตโนมัติใด ๆ สำหรับสไตล์นอกเหนือจากมนุษย์และสามัญสำนึก
David Rodríguez - dribeas

3
@ อานนท์อย่างไรก็ตามคุณได้รับการรับประกันว่าหากมีการโต้แย้งไม่ผ่านตัวชี้ก็จะไม่เปลี่ยนแปลง นั่นเป็นสิ่งที่มีค่ามากสำหรับ IMHO มิฉะนั้นเมื่อพยายามติดตามสิ่งที่เกิดขึ้นกับตัวแปรในฟังก์ชั่นคุณต้องตรวจสอบไฟล์ส่วนหัวของฟังก์ชั่นทั้งหมดที่ผ่านไปเพื่อตรวจสอบว่ามีการเปลี่ยนแปลงหรือไม่ ด้วยวิธีนี้คุณเพียงแค่ต้องดูสิ่งที่มันถูกส่งผ่านตัวชี้
smehmood

107

มีความแตกต่างบางอย่างในการเรียกประชุมใน C ++ และ Java ใน C ++ มีเทคนิคการพูดเพียงสองอนุสัญญา: pass-by-value และ pass-by-reference โดยมีวรรณกรรมบางอย่างรวมถึงระเบียบการส่งต่อโดยตัวชี้ที่สาม (นั่นคือการส่งต่อค่าของประเภทตัวชี้) นอกเหนือจากนั้นคุณสามารถเพิ่ม const-ness ให้กับชนิดของอาร์กิวเมนต์เพื่อเพิ่มความหมาย

ผ่านการอ้างอิง

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

ส่งผ่านค่า (และผ่านตัวชี้)

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

รุ่นพิเศษกำลังส่งตัวชี้ (ที่อยู่ของวัตถุ) ไปยังฟังก์ชัน ฟังก์ชั่นได้รับตัวชี้และการดำเนินการใด ๆ และทั้งหมดที่ใช้กับตัวชี้จะถูกนำไปใช้กับสำเนา (ตัวชี้) ในทางกลับกันการดำเนินการที่ใช้กับตัวชี้การลงทะเบียนจะใช้กับอินสแตนซ์วัตถุที่ตำแหน่งหน่วยความจำนั้น สามารถมีผลข้างเคียง ผลของการใช้ pass-by-value ของตัวชี้ไปยังวัตถุจะทำให้ฟังก์ชันภายในสามารถแก้ไขค่าภายนอกเช่นเดียวกับ pass-by-reference และจะอนุญาตให้มีค่าที่เป็นตัวเลือก (ผ่านตัวชี้ null)

นี่คือการประชุมที่ใช้ใน C เมื่อฟังก์ชั่นต้องการแก้ไขตัวแปรภายนอกและการประชุมที่ใช้ใน Java ที่มีประเภทการอ้างอิง: การอ้างอิงจะถูกคัดลอก แต่วัตถุที่อ้างถึงเหมือนกัน: การเปลี่ยนแปลงการอ้างอิง / ตัวชี้จะมองไม่เห็นภายนอก ฟังก์ชั่น แต่การเปลี่ยนแปลงหน่วยความจำแหลมเป็น

การเพิ่ม const ในสมการ

ใน C ++ คุณสามารถกำหนดค่าคงที่ให้กับวัตถุได้เมื่อกำหนดตัวแปรพอยน์เตอร์และการอ้างอิงในระดับต่าง ๆ คุณสามารถประกาศตัวแปรให้เป็นค่าคงที่คุณสามารถประกาศการอ้างอิงไปยังอินสแตนซ์คงที่และคุณสามารถกำหนดพอยน์เตอร์ทั้งหมดไปยังวัตถุคงที่พอยน์เตอร์คงที่ไปยังวัตถุที่ไม่แน่นอนและพอยน์เตอร์คงที่ ตรงกันข้ามใน Java คุณสามารถกำหนดหนึ่งระดับคงที่ (คำหลักสุดท้าย): ของตัวแปร (อินสแตนซ์สำหรับประเภทดั้งเดิมการอ้างอิงสำหรับประเภทการอ้างอิง) แต่คุณไม่สามารถกำหนดการอ้างอิงไปยังองค์ประกอบที่ไม่เปลี่ยนรูป ไม่เปลี่ยนรูป)

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

กฎของหัวแม่มือ

นี่เป็นกฎพื้นฐานบางประการที่จะต้องปฏิบัติตาม:

  • ชอบ pass-by-value สำหรับประเภทดั้งเดิม
  • ชอบ Pass-by-Reference พร้อมการอ้างอิงค่าคงที่สำหรับประเภทอื่น ๆ
  • หากฟังก์ชันจำเป็นต้องแก้ไขอาร์กิวเมนต์ให้ใช้การอ้างอิงแบบอ้างอิงถึงกัน
  • หากอาร์กิวเมนต์เป็นทางเลือกให้ใช้การบายพาสตัวชี้ (เป็นค่าคงที่หากไม่ใส่ค่าทางเลือก)

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

ข้อความด้านข้าง

สิ่งสำคัญคือต้องยืนยันในความสำคัญของความแตกต่างระหว่างการอ้างอิง C ++ และ Java ในการอ้างอิง C ++ เป็นแนวคิดของอินสแตนซ์ของวัตถุไม่ใช่ accessor ตัวอย่างที่ง่ายที่สุดคือการนำฟังก์ชัน swap ไปใช้:

// C++
class Type; // defined somewhere before, with the appropriate operations
void swap( Type & a, Type & b ) {
   Type tmp = a;
   a = b;
   b = tmp;
}
int main() {
   Type a, b;
   Type old_a = a, old_b = b;
   swap( a, b );
   assert( a == old_b );
   assert( b == old_a ); 
}

ฟังก์ชั่นการแลกเปลี่ยนด้านบนเปลี่ยนการขัดแย้งทั้งสองผ่านการใช้การอ้างอิง รหัสที่ใกล้เคียงที่สุดใน Java:

public class C {
   // ...
   public static void swap( C a, C b ) {
      C tmp = a;
      a = b;
      b = tmp;
   }
   public static void main( String args[] ) {
      C a = new C();
      C b = new C();
      C old_a = a;
      C old_b = b;
      swap( a, b ); 
      // a and b remain unchanged a==old_a, and b==old_b
   }
}

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


4
@ david-rodriguez-dribeas ฉันชอบกฎของส่วนหัวแม่มือโดยเฉพาะ "ชอบการส่งผ่านค่าสำหรับประเภทดั้งเดิม"
yadab

ตามที่ฉันนี้เป็นคำตอบที่ดีกว่าสำหรับคำถาม
unrealsoul007

22

มีหลายกรณีที่ต้องพิจารณา

แก้ไขพารามิเตอร์ (พารามิเตอร์ "ออก" และ "เข้า / ออก")

void modifies(T &param);
// vs
void modifies(T *param);

กรณีนี้ส่วนใหญ่เกี่ยวกับสไตล์: คุณต้องการให้โค้ดดูเหมือนcall (obj)หรือcall (& obj)หรือไม่? อย่างไรก็ตามมีสองจุดที่ความแตกต่างสำคัญ: ตัวเลือกกรณีด้านล่างและคุณต้องการใช้การอ้างอิงเมื่อตัวดำเนินการมากไป

... และไม่บังคับ

void modifies(T *param=0);  // default value optional, too
// vs
void modifies();
void modifies(T &param);

ไม่ได้แก้ไขพารามิเตอร์

void uses(T const &param);
// vs
void uses(T param);

นี่เป็นกรณีที่น่าสนใจ กฎของหัวแม่มือคือประเภท "ถูกคัดลอก" ถูกส่งผ่านโดยค่า - เหล่านี้โดยทั่วไปจะมีขนาดเล็กประเภท (แต่ไม่เสมอไป) - ในขณะที่คนอื่นจะถูกส่งผ่านโดยอ้างอิงอ้างอิง แต่ถ้าคุณต้องการที่จะทำสำเนาภายในฟังก์ชั่นของคุณไม่ว่าคุณควรจะผ่านโดยค่า (ใช่นี่จะเป็นการเปิดเผยรายละเอียดของการใช้งานเล็กน้อยC'est le C ++ )

... และไม่บังคับ

void uses(T const *param=0);  // default value optional, too
// vs
void uses();
void uses(T const &param);  // or optional(T param)

มีความแตกต่างน้อยที่สุดในทุกสถานการณ์ดังนั้นเลือกสิ่งที่ทำให้ชีวิตของคุณง่ายที่สุด

Const ตามค่าเป็นรายละเอียดการใช้งาน

void f(T);
void f(T const);

การประกาศเหล่านี้เป็นฟังก์ชั่นเดียวกันแน่นอน! เมื่อส่งผ่านค่า const จะเป็นรายละเอียดการใช้งานอย่างแท้จริง ลองดูสิ:

void f(int);
void f(int const) { /* implements above function, not an overload */ }

typedef void NC(int);       // typedefing function types
typedef void C(int const);

NC *nc = &f;  // nc is a function pointer
C *c = nc;    // C and NC are identical types

3
+1 ฉันไม่รู้เกี่ยวกับconstการใช้งานเมื่อผ่านไปตามค่า
balki

20

ผ่านมูลค่า:

void func (vector v)

ส่งผ่านตัวแปรตามค่าเมื่อฟังก์ชันต้องการการแยกอย่างสมบูรณ์จากสภาพแวดล้อมนั่นคือเพื่อป้องกันไม่ให้ฟังก์ชันแก้ไขตัวแปรดั้งเดิมเช่นเดียวกับเพื่อป้องกันไม่ให้เธรดอื่นปรับเปลี่ยนค่าของมันในขณะที่ฟังก์ชันกำลังทำงาน

ข้อเสียคือรอบของ CPU และหน่วยความจำพิเศษที่ใช้ในการคัดลอกวัตถุ

ผ่านการอ้างอิง const:

void func (const vector& v);

แบบฟอร์มนี้จำลองพฤติกรรมแบบ pass-by-value ในขณะที่ลบโอเวอร์เฮดการคัดลอก ฟังก์ชั่นได้รับการเข้าถึงแบบอ่านไปยังวัตถุต้นฉบับ แต่ไม่สามารถแก้ไขค่าได้

ข้อเสียคือความปลอดภัยของเธรด: การเปลี่ยนแปลงใด ๆ ที่ทำกับวัตถุต้นฉบับโดยเธรดอื่นจะปรากฏขึ้นภายในฟังก์ชันในขณะที่ยังคงดำเนินการอยู่

ผ่านการอ้างอิงที่ไม่ใช่แบบ const:

void func (vector& v)

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

เช่นเดียวกับกรณีอ้างอิง const นี่ไม่ใช่เธรดที่ปลอดภัย

ผ่านตัวชี้ const:

void func (const vector* vp);

ทำหน้าที่เหมือนกับ pass โดยการอ้างอิงแบบ const ยกเว้นไวยากรณ์ที่แตกต่างกันบวกกับความจริงที่ว่าฟังก์ชันการเรียกสามารถส่งผ่านตัวชี้ NULL เพื่อระบุว่าไม่มีข้อมูลที่ถูกต้องที่จะส่ง

ไม่ปลอดภัยสำหรับเธรด

ผ่านตัวชี้ที่ไม่ใช่ const:

void func (vector* vp);

คล้ายกับการอ้างอิงที่ไม่ใช่ const ผู้เรียกโดยทั่วไปตั้งค่าตัวแปรเป็น NULL เมื่อฟังก์ชันไม่ควรเขียนค่ากลับมา การประชุมนี้เห็นได้ในหลาย glibc API ตัวอย่าง:

void func (string* str, /* ... */) {
    if (str != NULL) {
        *str = some_value; // assign to *str only if it's non-null
    }
}

เช่นเดียวกับการส่งผ่านโดยการอ้างอิง / ตัวชี้ทั้งหมดไม่ใช่เธรดที่ปลอดภัย


0

เนื่องจากไม่มีใครพูดถึงฉันกำลังเพิ่มมันเมื่อคุณส่งวัตถุไปยังฟังก์ชันใน c ++ คอนสตรัคชันการคัดลอกเริ่มต้นของวัตถุนั้นจะถูกเรียกถ้าคุณไม่มีสิ่งที่สร้างโคลนของวัตถุแล้วส่งไปยังวิธีการดังนั้น เมื่อคุณเปลี่ยนค่าวัตถุที่จะสะท้อนให้เห็นถึงการคัดลอกวัตถุแทนที่จะเป็นวัตถุเดิมนั่นคือปัญหาใน c ++ ดังนั้นถ้าคุณทำให้ทุกระดับของคุณลักษณะเป็นตัวชี้แล้วตัวสร้างการคัดลอกจะคัดลอกที่อยู่ของ คุณสมบัติตัวชี้ดังนั้นเมื่อวิธีการ invocations บนวัตถุที่จัดการกับค่าที่เก็บไว้ในที่อยู่แอตทริบิวต์ตัวชี้การเปลี่ยนแปลงก็สะท้อนให้เห็นในวัตถุต้นฉบับที่ถูกส่งผ่านเป็นพารามิเตอร์เพื่อให้สามารถทำงานได้เหมือนกัน Java แต่อย่าลืมว่าทุกชั้นเรียนของคุณ คุณลักษณะต้องเป็นตัวชี้นอกจากนี้คุณควรเปลี่ยนค่าของตัวชี้จะมีความชัดเจนมากพร้อมคำอธิบายรหัส

Class CPlusPlusJavaFunctionality {
    public:
       CPlusPlusJavaFunctionality(){
         attribute = new int;
         *attribute = value;
       }

       void setValue(int value){
           *attribute = value;
       }

       void getValue(){
          return *attribute;
       }

       ~ CPlusPlusJavaFuncitonality(){
          delete(attribute);
       }

    private:
       int *attribute;
}

void changeObjectAttribute(CPlusPlusJavaFunctionality obj, int value){
   int* prt = obj.attribute;
   *ptr = value;
}

int main(){

   CPlusPlusJavaFunctionality obj;

   obj.setValue(10);

   cout<< obj.getValue();  //output: 10

   changeObjectAttribute(obj, 15);

   cout<< obj.getValue();  //output: 15
}

แต่นี่ไม่ใช่ความคิดที่ดีเพราะคุณจะต้องเขียนโค้ดจำนวนมากที่เกี่ยวข้องกับพอยน์เตอร์ซึ่งมีแนวโน้มที่จะเกิดการรั่วไหลของหน่วยความจำและอย่าลืมเรียก destructors และเพื่อหลีกเลี่ยง c ++ นี้จะมีตัวสร้างสำเนาที่คุณจะสร้างหน่วยความจำใหม่เมื่อวัตถุที่มีตัวชี้ถูกส่งผ่านไปยังอาร์กิวเมนต์ของฟังก์ชันซึ่งจะหยุดจัดการข้อมูลวัตถุอื่น ๆ Java จะผ่านค่าและค่าเป็นการอ้างอิงดังนั้นจึงไม่ต้องการตัวสร้างสำเนา


-1

มีสามวิธีในการส่งวัตถุไปยังฟังก์ชั่นเป็นพารามิเตอร์:

  1. ผ่านการอ้างอิง
  2. ผ่านค่า
  3. การเพิ่มค่าคงที่ในพารามิเตอร์

ทำตามตัวอย่างต่อไปนี้:

class Sample
{
public:
    int *ptr;
    int mVar;

    Sample(int i)
    {
        mVar = 4;
        ptr = new int(i);
    }

    ~Sample()
    {
        delete ptr;
    }

    void PrintVal()
    {
        cout << "The value of the pointer is " << *ptr << endl
             << "The value of the variable is " << mVar;
   }
};

void SomeFunc(Sample x)
{
cout << "Say i am in someFunc " << endl;
}


int main()
{

  Sample s1= 10;
  SomeFunc(s1);
  s1.PrintVal();
  char ch;
  cin >> ch;
}

เอาท์พุท:

บอกว่าฉันอยู่ใน someFunc
ค่าของตัวชี้คือ -17891602
ค่าของตัวแปรคือ 4


มีเพียง 2 วิธี (2 คนแรกที่คุณพูดถึง) ไม่ทราบว่าคุณหมายถึงอะไรโดย "ผ่านค่าคงที่ในพารามิเตอร์"
MM

-1

ต่อไปนี้เป็นวิธีการส่งอาร์กิวเมนต์ / พารามิเตอร์เพื่อทำงานใน C ++

1. ตามค่า

// passing parameters by value . . .

void foo(int x) 
{
    x = 6;  
}

2. โดยการอ้างอิง

// passing parameters by reference . . .

void foo(const int &x) // x is a const reference
{
    x = 6;  
}

// passing parameters by const reference . . .

void foo(const int &x) // x is a const reference
{
    x = 6;  // compile error: a const reference cannot have its value changed!
}

3. ตามวัตถุ

class abc
{
    display()
    {
        cout<<"Class abc";
    }
}


// pass object by value
void show(abc S)
{
    cout<<S.display();
}

// pass object by reference
void show(abc& S)
{
    cout<<S.display();
}

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