ตัวชี้เทียบกับค่าในพารามิเตอร์และค่าส่งคืน


328

ในการไปมีหลายวิธีในการคืนstructค่าหรือชิ้นส่วนดังกล่าว สำหรับคนที่ฉันเคยเห็น:

type MyStruct struct {
    Val int
}

func myfunc() MyStruct {
    return MyStruct{Val: 1}
}

func myfunc() *MyStruct {
    return &MyStruct{}
}

func myfunc(s *MyStruct) {
    s.Val = 1
}

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

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

ในทำนองเดียวกันคำถามเดียวกันเกี่ยวกับชิ้น:

func myfunc() []MyStruct {
    return []MyStruct{ MyStruct{Val: 1} }
}

func myfunc() []*MyStruct {
    return []MyStruct{ &MyStruct{Val: 1} }
}

func myfunc(s *[]MyStruct) {
    *s = []MyStruct{ MyStruct{Val: 1} }
}

func myfunc(s *[]*MyStruct) {
    *s = []MyStruct{ &MyStruct{Val: 1} }
}

อีกครั้ง: สิ่งที่เป็นแนวทางปฏิบัติที่ดีที่สุดที่นี่ ฉันรู้ว่าสไลซ์เป็นพอยน์เตอร์เสมอดังนั้นการคืนค่าพอยน์เตอร์ไปยังชิ้นจึงไม่เป็นประโยชน์ อย่างไรก็ตามฉันควรส่งคืนค่า struct เป็นชิ้นส่วนของพอยน์เตอร์ไปยัง struct ฉันควรส่งผ่านตัวชี้ไปยังชิ้นเป็นอาร์กิวเมนต์ (รูปแบบที่ใช้ในGo App Engine API ) หรือไม่


1
อย่างที่คุณพูดมันขึ้นอยู่กับกรณีการใช้งาน ทั้งหมดถูกต้องขึ้นอยู่กับสถานการณ์ - นี่เป็นวัตถุที่ไม่แน่นอนหรือไม่? เราต้องการคัดลอกหรือตัวชี้? ฯลฯ BTW คุณไม่ได้พูดถึงการใช้new(MyStruct):) แต่ไม่มีความแตกต่างระหว่างวิธีการจัดสรรพอยน์เตอร์และการส่งคืน
Not_a_Golfer

15
นั่นคือวิศวกรรมอย่างแท้จริง โครงสร้างต้องมีขนาดใหญ่พอที่จะให้ตัวชี้กลับมาทำให้โปรแกรมเร็วขึ้น ไม่ต้องกังวลรหัสโปรไฟล์แก้ไขหากมีประโยชน์
Volker

1
มีเพียงวิธีเดียวในการส่งคืนค่าหรือตัวชี้และนั่นคือการคืนค่าหรือตัวชี้ วิธีการจัดสรรเป็นประเด็นแยกต่างหาก ใช้สิ่งที่ได้ผลกับสถานการณ์ของคุณและไปเขียนโค้ดก่อนที่คุณจะกังวล
JimB

3
BTW เพิ่งออกมาด้วยความอยากรู้ การคืนค่า structs กับพอยน์เตอร์ดูเหมือนว่าจะมีความเร็วเท่ากัน แต่การส่งพอยน์เตอร์ไปยังฟังก์ชั่นที่ลงมานั้นเร็วขึ้นอย่างมาก แม้ว่าจะไม่ได้อยู่ในระดับนั้นก็เป็นเรื่องสำคัญ
Not_a_Golfer

1
@Not_a_Golfer: ฉันคิดว่านั่นเป็นเพียงแค่การจัดสรร bc เท่านั้นที่ทำนอกฟังก์ชั่น นอกจากนี้ค่าการเทียบกับพอยน์เตอร์ยังขึ้นอยู่กับขนาดของรูปแบบการเข้าถึงโครงสร้างและหน่วยความจำหลังจากข้อเท็จจริง การคัดลอกสิ่งที่มีขนาดแคชบรรทัดเร็วที่สุดเท่าที่คุณจะทำได้และความเร็วของการยกเลิกการประชุมพอยน์เตอร์จาก CPU cache นั้นแตกต่างจากการยกเลิกการอ้างอิงจากหน่วยความจำหลัก
JimB

คำตอบ:


392

tl; dr :

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

กรณีหนึ่งที่คุณควรใช้ตัวชี้บ่อย:

  • ผู้รับ เป็นตัวชี้บ่อยกว่าข้อโต้แย้งอื่น ๆ มันไม่ใช่เรื่องแปลกสำหรับวิธีการแก้ไขสิ่งที่พวกเขาเรียกหรือประเภทที่มีชื่อเป็น structs ขนาดใหญ่ดังนั้นคำแนะนำคือการเริ่มต้นที่ตัวชี้ยกเว้นในกรณีที่หายาก
    • เครื่องมือcopyfighterของ Jeff Hodges จะค้นหาตัวรับสัญญาณที่ไม่ใช่ตัวเล็กโดยอัตโนมัติผ่านค่า

บางสถานการณ์ที่คุณไม่ต้องการตัวชี้:

  • แนวทางการตรวจสอบโค้ดแนะนำให้ส่งผ่านโครงสร้างขนาดเล็กเช่นtype Point struct { latitude, longitude float64 }และอาจเป็นเรื่องที่ใหญ่ขึ้นเล็กน้อยเป็นค่าเว้นแต่ฟังก์ชันที่คุณโทรต้องสามารถแก้ไขได้

    • ซีแมนทิกส์มูลค่าหลีกเลี่ยงสถานการณ์การใช้นามแฝงซึ่งการมอบหมายที่นี่เปลี่ยนค่าโดยไม่คาดคิด
    • ไม่ใช่ Go-y ที่จะเสียสละซีแมนติกที่สะอาดด้วยความเร็วเพียงเล็กน้อยและบางครั้งการส่งผ่านโครงสร้างขนาดเล็กตามค่านั้นมีประสิทธิภาพมากกว่าเพราะหลีกเลี่ยงการใช้แคชหรือการจัดสรรฮีป
    • ดังนั้นหน้าความคิดเห็นการตรวจสอบรหัสของ Go Wiki แนะนำให้ส่งผ่านค่าเมื่อ structs มีขนาดเล็กและมีแนวโน้มที่จะอยู่แบบนั้น
    • หากทางลัด "ใหญ่" ดูเหมือนคลุมเครือนั่นคือ มีโครงสร้างจำนวนมากที่อยู่ในช่วงที่ตัวชี้หรือค่าตกลง ในฐานะที่เป็นขอบเขตล่างความคิดเห็นตรวจสอบรหัสแนะนำชิ้น (สามคำเครื่อง) มีเหตุผลที่จะใช้เป็นตัวรับค่า ในฐานะที่เป็นสิ่งที่ใกล้กับขอบเขตบนbytes.Replaceใช้ค่า args 10 คำ (สามส่วนและint)
  • สำหรับสไลซ์คุณไม่จำเป็นต้องผ่านตัวชี้เพื่อเปลี่ยนองค์ประกอบของอาเรย์ ตัวอย่างเช่นio.Reader.Read(p []byte)เปลี่ยนไบต์ pอาจเป็นกรณีพิเศษของ "จัดการกับโครงสร้างเล็ก ๆ น้อย ๆ เช่นค่า" เนื่องจากภายในคุณกำลังผ่านโครงสร้างเล็ก ๆ ที่เรียกว่าส่วนหัวฝาน (ดูคำอธิบายของ Russ Cox (rsc) ) ในทำนองเดียวกันคุณไม่จำเป็นต้องชี้ไปปรับเปลี่ยนแผนที่หรือสื่อสารในช่อง

  • สำหรับชิ้นส่วนที่คุณจะต้องเปลี่ยน (เปลี่ยนเริ่มต้น / ความยาว / ความจุของ) ฟังก์ชั่นในตัวเช่นappendยอมรับค่าชิ้นและส่งคืนใหม่ ฉันเลียนแบบ; มันหลีกเลี่ยงการสร้างสมนามคืนชิ้นใหม่ช่วยให้ทราบถึงความจริงที่ว่าอาร์เรย์ใหม่อาจถูกจัดสรรและคุ้นเคยกับผู้โทร

    • มันไม่ได้เป็นไปตามรูปแบบนั้นเสมอไป เครื่องมือบางอย่างเช่นอินเทอร์เฟซฐานข้อมูลหรือซีเรียลไลเซอร์จำเป็นต้องผนวกส่วนที่ไม่รู้จักชนิดในเวลารวบรวม บางครั้งพวกเขาก็ยอมรับตัวชี้ไปยังส่วนหนึ่งในinterface{}พารามิเตอร์
  • แผนที่ช่องสตริงและฟังก์ชันและค่าอินเทอร์เฟซเช่นส่วนแบ่งเป็นการอ้างอิงภายในหรือโครงสร้างที่มีการอ้างอิงอยู่แล้วดังนั้นหากคุณเพียงพยายามหลีกเลี่ยงการคัดลอกข้อมูลพื้นฐานคุณไม่จำเป็นต้องส่งพอยน์เตอร์ไปให้พวกเขา . (rsc เขียนบทความแยกต่างหากเกี่ยวกับวิธีการเก็บค่าอินเทอร์เฟซ )

    • คุณยังอาจต้องส่งพอยน์เตอร์ในกรณีที่หายากที่คุณต้องการปรับเปลี่ยนโครงสร้างของผู้เรียกflag.StringVarใช้*stringตัวอย่างเช่น

ตำแหน่งที่คุณใช้พอยน์เตอร์:

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

  • ฟังก์ชั่นที่มีผลกระทบกับ params ที่ไม่ใช่ผู้รับควรทำให้ชัดเจนใน godoc หรือดีกว่านั้น godoc และชื่อ (เช่นreader.WriteTo(writer))

  • คุณพูดถึงการยอมรับตัวชี้เพื่อหลีกเลี่ยงการจัดสรรโดยอนุญาตให้ใช้ซ้ำได้ การเปลี่ยน API เพื่อนำหน่วยความจำกลับมาใช้เป็นการเพิ่มประสิทธิภาพที่ฉันจะหน่วงเวลาจนกว่าจะชัดเจนว่าการจัดสรรมีค่าใช้จ่ายที่ไม่สำคัญและจากนั้นฉันจะมองหาวิธีที่ไม่ได้บังคับให้ผู้ใช้ API หลอกลวงกว่า:

    1. สำหรับการหลีกเลี่ยงการจัดสรรการวิเคราะห์การหลบหนีของ Go เป็นเพื่อนของคุณ bytes.Bufferบางครั้งคุณสามารถช่วยได้หลีกเลี่ยงการจัดสรรกองโดยการทำชนิดที่สามารถเริ่มต้นได้ด้วยตัวสร้างเล็กน้อยตัวอักษรธรรมดาหรือที่มีประโยชน์เช่นค่าเป็นศูนย์
    2. พิจารณาReset()วิธีที่จะทำให้วัตถุกลับสู่สถานะว่างเหมือนที่ stdlib บางประเภทเสนอ ผู้ใช้ที่ไม่สนใจหรือไม่สามารถบันทึกการจัดสรรไม่ต้องโทร
    3. พิจารณาการเขียนฟังก์ชั่นการปรับเปลี่ยนในสถานที่วิธีการและสร้างจากรอยขีดข่วนเป็นคู่จับคู่เพื่อความสะดวก: อาจจะห่อโดยexistingUser.LoadFromJSON(json []byte) error NewUserFromJSON(json []byte) (*User, error)อีกครั้งมันผลักดันทางเลือกระหว่างความเกียจคร้านและการจัดสรรการบีบให้ผู้เรียกแต่ละคน
    4. ผู้โทรที่ต้องการรีไซเคิลหน่วยความจำสามารถให้sync.Poolรายละเอียดบางอย่างได้ หากการจัดสรรเฉพาะสร้างแรงกดดันหน่วยความจำมากคุณมั่นใจว่าคุณรู้เมื่อไม่มีการจัดสรรอีกต่อไปและคุณไม่มีการเพิ่มประสิทธิภาพที่ดีขึ้นsync.Poolสามารถช่วยได้ (CloudFlare เผยแพร่โพสต์บล็อกที่มีประโยชน์ (ก่อนsync.Pool)เกี่ยวกับการรีไซเคิล)

ในที่สุดว่าชิ้นของคุณควรเป็นพอยน์เตอร์หรือไม่: ชิ้นส่วนของค่ามีประโยชน์และช่วยให้คุณจัดสรรและแคชไม่ได้ อาจมีบล็อค:

  • API ที่จะสร้างรายการของคุณอาจจะบังคับให้คำแนะนำเกี่ยวกับคุณเช่นคุณมีการโทรNewFoo() *Fooมากกว่าปล่อยให้ไปเริ่มต้นกับค่าเป็นศูนย์
  • อายุการใช้งานที่ต้องการของรายการอาจไม่เหมือนกันทั้งหมด ชิ้นส่วนทั้งหมดจะถูกปลดปล่อยในครั้งเดียว หากรายการ 99% ไม่มีประโยชน์อีกต่อไป แต่คุณมีตัวชี้ไปยังอีก 1% อาร์เรย์ทั้งหมดจะยังคงถูกจัดสรร
  • การย้ายสิ่งของไปมาอาจทำให้คุณมีปัญหา โดยเฉพาะอย่างยิ่งappendรายการสำเนาเมื่อมันเติบโตอาร์เรย์พื้นฐาน ตัวชี้ที่คุณได้รับก่อนที่จะappendชี้ไปยังตำแหน่งที่ไม่ถูกต้องหลังจากนั้นการคัดลอกอาจช้าลงสำหรับโครงสร้างขนาดใหญ่และsync.Mutexไม่อนุญาตให้ทำการคัดลอกเช่น แทรก / ลบตรงกลางและจัดเรียงรายการที่คล้ายกันย้ายไปมา

ในวงกว้างคุณค่าของชิ้นงานสามารถทำให้เข้าใจได้ถ้าคุณได้สิ่งของทั้งหมดมาวางไว้ด้านหน้าและอย่าขยับ (เช่นไม่มีappendการตั้งค่าเริ่มต้นอีกต่อไป) หรือถ้าคุณเคลื่อนไหวไปเรื่อย ๆ แต่คุณแน่ใจ ตกลง (ไม่มีการใช้พอยน์เตอร์อย่างระมัดระวัง / รายการมีขนาดเล็กพอที่จะคัดลอกอย่างมีประสิทธิภาพ ฯลฯ ) บางครั้งคุณต้องคิดถึงหรือวัดเฉพาะสถานการณ์ของคุณ แต่เป็นแนวทางคร่าวๆ


12
โครงสร้างขนาดใหญ่หมายถึงอะไร มีตัวอย่างของโครงสร้างขนาดใหญ่และโครงสร้างขนาดเล็กหรือไม่?
ผู้ใช้ที่ไม่มีหมวก

1
คุณบอกไบต์ได้อย่างไรแทนที่ได้ค่า args 80 ไบต์ใน amd64
Tim Wu

2
ลายเซ็นคือReplace(s, old, new []byte, n int) []byte; s, old และ new เป็นสามคำแต่ละคำ ( ส่วนแบ่งเป็น(ptr, len, cap) ) และn intเป็นหนึ่งคำดังนั้น 10 คำซึ่งที่แปดไบต์ / คำคือ 80 ไบต์
twotwotwo

6
คุณจะกำหนดโครงสร้างขนาดใหญ่ได้อย่างไร ใหญ่แค่ไหน
Andy Aldo

3
@AndyAldo ไม่มีแหล่งที่มาของฉัน (ความเห็นการตรวจสอบรหัส ฯลฯ ) กำหนดเกณฑ์ดังนั้นฉันตัดสินใจที่จะพูดว่ามันเป็นการเรียกการตัดสินใจแทนการทำเกณฑ์ สามคำ (เช่นชิ้น) ถือว่าเป็นสิทธิอย่างต่อเนื่องที่จะเป็นค่าใน stdlib ฉันพบอินสแตนซ์ของตัวรับค่าห้าคำในตอนนี้ (ข้อความ / สแกนเนอร์ตำแหน่ง) แต่ฉันไม่ได้อ่านอะไรมากมาย (มันก็ผ่านเป็นตัวชี้!) ไม่มีมาตรฐาน ฯลฯ ฉันแค่ทำทุกอย่างที่สะดวกที่สุดในการอ่าน
twotwotwo

10

สามเหตุผลหลักเมื่อคุณต้องการใช้เมธอดรับเป็นพอยน์เตอร์:

  1. "ขั้นแรกและสำคัญที่สุดวิธีการนั้นจำเป็นต้องแก้ไขตัวรับหรือไม่ถ้าทำได้ตัวรับจะต้องเป็นตัวชี้"

  2. "ประการที่สองคือการพิจารณาประสิทธิภาพหากตัวรับสัญญาณมีขนาดใหญ่ตัวอย่างเช่นโครงสร้างขนาดใหญ่มันจะถูกกว่ามากหากใช้ตัวรับสัญญาณตัวชี้"

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

การอ้างอิง: https://golang.org/doc/faq#methods_on_values_or_pointers

แก้ไข: อีกสิ่งสำคัญคือการรู้ "ประเภท" จริงที่คุณส่งไปยังฟังก์ชั่น ประเภทนี้อาจเป็น 'ประเภทค่า' หรือ 'ประเภทอ้างอิง'

แม้ในขณะที่ชิ้นส่วนและแผนที่ทำหน้าที่เป็นข้อมูลอ้างอิงเราอาจต้องการส่งผ่านเป็นตัวชี้ในสถานการณ์จำลองเช่นการเปลี่ยนความยาวของชิ้นในฟังก์ชัน


1
สำหรับ 2 สิ่งที่ถูกตัดออก? ฉันจะรู้ได้อย่างไรว่าโครงสร้างของฉันเล็กหรือใหญ่ นอกจากนี้ยังจะมีโครงสร้างที่มีขนาดเล็กพอดังกล่าวว่ามันเป็นมากขึ้นมีประสิทธิภาพในการใช้ค่ามากกว่าตัวชี้ (เพื่อว่ามันไม่ได้จะต้องมีการอ้างอิงจากกอง)?
zlotnika

ฉันจะบอกว่ายิ่งจำนวนของเขตข้อมูลและ / หรือโครงสร้างซ้อนกันภายในยิ่งโครงสร้างมีขนาดใหญ่ขึ้น ฉันไม่แน่ใจว่ามีทางลัดที่เฉพาะเจาะจงหรือวิธีการมาตรฐานที่จะรู้เมื่อโครงสร้างสามารถเรียกว่า "ใหญ่" หรือ "ใหญ่" ถ้าฉันใช้หรือสร้าง struct ฉันจะรู้ว่ามันเล็กหรือใหญ่ขึ้นอยู่กับสิ่งที่ฉันพูดไป แต่นั่นเป็นเพียงฉัน!
Santosh Pillai

2

กรณีที่คุณต้องส่งคืนพอยน์เตอร์โดยทั่วไปคือเมื่อสร้างอินสแตนซ์ของทรัพยากรที่รัฐหรือใช้ร่วมกันได้ สิ่งนี้มักจะทำโดยฟังก์ชั่นที่Newขึ้นต้นด้วย

เนื่องจากมันเป็นตัวแทนของอินสแตนซ์ที่เฉพาะเจาะจงของบางสิ่งบางอย่างและพวกเขาอาจต้องการประสานงานบางกิจกรรมจึงไม่เหมาะสมที่จะสร้างโครงสร้างที่ทำซ้ำ / คัดลอกซึ่งแสดงถึงทรัพยากรเดียวกัน - ดังนั้นตัวชี้ที่ส่งคืนจะทำหน้าที่เป็นตัวจัดการทรัพยากร .

ตัวอย่างบางส่วน:

ในกรณีอื่นพอยน์เตอร์จะถูกส่งคืนเนื่องจากโครงสร้างอาจใหญ่เกินไปที่จะคัดลอกโดยค่าเริ่มต้น:


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


โดยปริยายในการวิเคราะห์นี้คือโดยค่าเริ่มต้น struct จะถูกคัดลอกตามค่า (แต่ไม่จำเป็นต้องเป็นสมาชิกทางอ้อม)
สูงศักดิ์

2

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

  1. รหัสของคุณจะดีและอ่านได้มากขึ้นหลีกเลี่ยงตัวดำเนินการตัวชี้และการตรวจสอบค่า Null
  2. รหัสของคุณปลอดภัยกว่า Null Pointer panic
  3. รหัสของคุณจะเร็วขึ้น: ใช่เร็วกว่า! ทำไม?

เหตุผลที่ 1 : คุณจะจัดสรรรายการน้อยลงในสแต็ก การจัดสรร / การจัดสรรคืนจากสแต็กนั้นเกิดขึ้นทันที แต่การจัดสรร / การจัดสรรคืนบนฮีปอาจมีราคาแพงมาก (เวลาการจัดสรร + การรวบรวมขยะ) คุณสามารถดูหมายเลขพื้นฐานได้ที่นี่: http://www.macias.info/entry/201802102230_go_values_vs_references.md

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

ตัวทำลายตำนาน : บรรทัดแคช x86 ทั่วไปคือ 64 ไบต์ structs ส่วนใหญ่มีขนาดเล็กกว่านั้น เวลาในการคัดลอกบรรทัดแคชในหน่วยความจำคล้ายกับการคัดลอกตัวชี้

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

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