ความถูกต้องของ const สามารถปรับปรุงประสิทธิภาพได้หรือไม่?


92

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

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


50
ความถูกต้องของค่าคงที่เป็นหนึ่งในแนวทางปฏิบัติที่ดีที่สุดสำหรับการบำรุงรักษา หากรหัส C ++ ของคุณไม่ถูกต้องโดยพื้นฐานแล้วจะเป็นกองขยะรอให้หายนะโจมตี ไม่ได้มีวัตถุประสงค์เพื่อส่งผลกระทบต่อประสิทธิภาพ

2
@ นีลบัตเตอร์เวิร์ ธ : น่าเสียดายที่ผกผันไม่เป็นความจริง
เบต้า

6
นี่คือตัวอย่างที่ซึ่งconstทำให้ความแตกต่างประสิทธิภาพ: stackoverflow.com/questions/1121791/... โดยพื้นฐานแล้วเป็นปัญหาด้านคุณภาพของการนำไปใช้งาน constไม่ได้ระบุว่าคอมไพลเลอร์สามารถทำการปรับให้เหมาะสมได้อย่างถูกกฎหมายหรือไม่ แต่เพิ่งเกิดขึ้นที่เวอร์ชันของคอมไพเลอร์ล้มเหลวในการสร้างเมื่อมันหายไป
Steve Jessop

3
ฉันค่อนข้างแน่ใจว่า "morgennebel" พลาด "เฉพาะ" ในประโยคแรก: มันเข้าท่ากว่ามากกับ "ไม่ใช่แค่แนวทางปฏิบัติที่ดีเท่านั้น"
IanH

2
@IanH ใช่ฉันพิจารณาแล้ว แต่ OP มีเวลาเพียงพอที่จะชี้แจง ฉันโดนคนที่โพสต์คำถามจริงๆแล้วก็หายไป

คำตอบ:


77

constความถูกต้องไม่สามารถปรับปรุงประสิทธิภาพได้เนื่องจากconst_castและmutableเป็นภาษาและอนุญาตให้โค้ดละเมิดกฎได้ สิ่งนี้จะแย่ลงใน C ++ 11 โดยที่constข้อมูลของคุณอาจเป็นตัวชี้ไปยัง a std::atomicซึ่งหมายความว่าคอมไพเลอร์ต้องเคารพการเปลี่ยนแปลงที่เกิดขึ้นโดยเธรดอื่น

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

ที่กล่าวมาทั้งหมดconstความถูกต้องเป็นสิ่งที่ดีสำหรับการบำรุงรักษา มิฉะนั้นลูกค้าในชั้นเรียนของคุณอาจทำลายสมาชิกภายในของชั้นเรียนนั้นได้ ตัวอย่างเช่นพิจารณามาตรฐานstd::string::c_str()- หากไม่สามารถคืนค่า const ได้คุณจะสามารถใช้บัฟเฟอร์ภายในของสตริงได้!

อย่าใช้constเพื่อเหตุผลด้านประสิทธิภาพ ใช้เพื่อเหตุผลด้านการบำรุงรักษา


31
"คุณจะสามารถใช้บัฟเฟอร์ภายในของสตริงได้!" - ขับเคลื่อนคุณจะสามารถตั้งใจกรูรอบกับบัฟเฟอร์ภายใน ข้อผิดพลาดของคอมไพเลอร์เนื่องจากconstเป็นป้ายบอกทางบอกว่า "คุณทำอะไรโง่ ๆ "
Steve Jessop

4
... และ const-casts คือป้ายบอกทางที่บอกว่า "ผู้เขียนรหัสนี้พยายามทำอะไรที่ฉลาด" ;-)
Steve Jessop

5
@Steve Jessop - หรือ const-cast คือป้ายบอกทางที่บอกว่า "ฉันกำลังพยายามใส่รหัสกลุ่มที่ถูกต้องเป็น const ให้เป็นรหัสที่ไม่ถูกต้องและฉันไม่สามารถแก้ไขได้" ซึ่งให้ฉันบอกคุณว่ามันไม่ฉลาดแค่น่ารำคาญ
Michael Kohne

7
@ ไมเคิล - ใช่จุดยุติธรรม บางทีป้ายบอกทางเดิมอาจไม่ใช่ "คุณกำลังทำอะไรโง่ ๆ " แต่เป็น "ใครบางคนกำลังทำอะไรโง่ ๆ "
Steve Jessop

Godbolt และ Arduino บอกฉันว่าความถูกต้องของ const ไม่ใช่แค่เพื่อความสนุกสนาน
dgrat

31

ใช่มันทำได้

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

ตัวอย่างเช่นการเข้าถึงตัวแปรส่วนกลางที่กำหนดด้วยconstประเภทสามารถอินไลน์ได้ในขณะที่ไม่สามารถอินไลน์อินไลน์ที่ไม่มีconstประเภทได้เนื่องจากอาจมีการเปลี่ยนแปลงเมื่อรันไทม์

https://godbolt.org/g/UEX4NB

C ++:

int foo1 = 1;
const int foo2 = 2;

int get_foo1() {
    return foo1;
}

int get_foo2() {
    return foo2;
}

asm:

foo1:
        .long   1
foo2:
        .long   2
get_foo1():
        push    rbp
        mov     rbp, rsp
        mov     eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address
        pop     rbp
        ret
get_foo2():
        push    rbp
        mov     rbp, rsp
        mov     eax, 2 ; foo2 has been replaced with an immediate 2
        pop     rbp
        ret

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


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


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

1
@Acorn นี่คือตัวอย่างเดียวกัน แต่มีวัตถุชั้นเรียน: godbolt.org/z/R-Zfgc นอกจากนี้ตัวแปรในตัวอย่างยังมีการเชื่อมโยงภายนอก
Praxeolitic

6

จากประสบการณ์ของฉันไม่

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

สำหรับตัวชี้อาร์เรย์ความถูกต้องของ const ไม่สามารถรับประกันได้ว่าค่าจะคงที่จริง ๆ เมื่อมีปัญหานามแฝงที่อาจเกิดขึ้น ดังนั้นคอมไพเลอร์ไม่สามารถใช้ตัวปรับแต่ง const เพียงอย่างเดียวเพื่อทำการปรับให้เหมาะสม

หากคุณกำลังมองหาการเพิ่มประสิทธิภาพคุณควรพิจารณา__restrict__หรือตัวปรับแต่งฟังก์ชันพิเศษ / แอตทริบิวต์: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html


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