พิจารณา:
int testfunc1 (const int a)
{
return a;
}
int testfunc2 (int const a)
{
return a;
}
สองหน้าที่นี้เหมือนกันทุกประการหรือไม่หรือมีความแตกต่างกันอย่างไร?
ฉันสนใจคำตอบสำหรับภาษา C แต่ถ้ามีอะไรน่าสนใจในภาษา C ++ ฉันก็อยากรู้เช่นกัน
พิจารณา:
int testfunc1 (const int a)
{
return a;
}
int testfunc2 (int const a)
{
return a;
}
สองหน้าที่นี้เหมือนกันทุกประการหรือไม่หรือมีความแตกต่างกันอย่างไร?
ฉันสนใจคำตอบสำหรับภาษา C แต่ถ้ามีอะไรน่าสนใจในภาษา C ++ ฉันก็อยากรู้เช่นกัน
คำตอบ:
const T
และT const
เหมือนกัน ด้วยประเภทตัวชี้จะซับซ้อนมากขึ้น:
const char*
เป็นตัวชี้ค่าคงที่ char
char const*
เป็นตัวชี้ค่าคงที่ char
char* const
เป็นตัวชี้ค่าคงที่ไปยัง a (เปลี่ยนแปลงได้) char
กล่าวอีกนัยหนึ่ง (1) และ (2) เหมือนกัน วิธีเดียวในการสร้างตัวชี้ (แทนที่จะเป็นพอยน์เตอร์) const
คือการใช้คำต่อท้ายconst
-
นี่คือเหตุผลที่หลายคนชอบวางประเภทconst
ให้ถูกต้องเสมอ(รูปแบบ“ East const”): ทำให้ตำแหน่งของมันสัมพันธ์กับประเภทที่สอดคล้องกันและง่ายต่อการจดจำ (นอกจากนี้ยังดูเหมือนว่าจะทำให้ง่ายต่อการสอนสำหรับผู้เริ่มต้น )
เคล็ดลับคือการอ่านคำประกาศย้อนหลัง (ขวาไปซ้าย):
const int a = 1; // read as "a is an integer which is constant"
int const a = 1; // read as "a is a constant integer"
ทั้งสองอย่างคือสิ่งเดียวกัน ดังนั้น:
a = 2; // Can't do because a is constant
เคล็ดลับการอ่านย้อนหลังมีประโยชน์อย่างยิ่งเมื่อคุณต้องจัดการกับการประกาศที่ซับซ้อนมากขึ้นเช่น:
const char *s; // read as "s is a pointer to a char that is constant"
char c;
char *const t = &c; // read as "t is a constant pointer to a char"
*s = 'A'; // Can't do because the char is constant
s++; // Can do because the pointer isn't constant
*t = 'A'; // Can do because the char isn't constant
t++; // Can't do because the pointer is constant
char const *
อ่านจากซ้ายไปขวาคือ: "pointer, const, char" เป็นตัวชี้ไปยัง const char เมื่อคุณพูดว่า "ตัวชี้ที่คงที่" คำคุณศัพท์ "ค่าคงที่" จะอยู่บนตัวชี้ ดังนั้นในกรณีนี้รายการคำคุณศัพท์ของคุณควรเป็น: "const, pointer, char" จริงๆ แต่คุณพูดถูกมีความคลุมเครือสำหรับเคล็ดลับนี้ มันเป็น "เคล็ดลับ" จริงๆมากกว่า "กฎ" ที่ชัดเจน
ไม่มีความแตกต่างกัน ทั้งสองประกาศว่า "a" เป็นจำนวนเต็มที่ไม่สามารถเปลี่ยนแปลงได้
สถานที่ที่ความแตกต่างเริ่มปรากฏคือเมื่อคุณใช้พอยน์เตอร์
ทั้งสองอย่างนี้:
const int *a
int const *a
ประกาศ "a" เพื่อเป็นตัวชี้ไปยังจำนวนเต็มที่ไม่เปลี่ยนแปลง "a" สามารถกำหนดให้ แต่ "* a" ไม่ได้
int * const a
ประกาศว่า "a" เป็นตัวชี้ค่าคงที่เป็นจำนวนเต็ม สามารถกำหนด "* a" ให้ แต่ "a" ไม่ได้
const int * const a
ประกาศว่า "a" เป็นตัวชี้ค่าคงที่เป็นจำนวนเต็มคงที่ ไม่สามารถกำหนด "a" หรือ "* a" ให้ได้
static int one = 1;
int testfunc3 (const int *a)
{
*a = 1; /* Error */
a = &one;
return *a;
}
int testfunc4 (int * const a)
{
*a = 1;
a = &one; /* Error */
return *a;
}
int testfunc5 (const int * const a)
{
*a = 1; /* Error */
a = &one; /* Error */
return *a;
}
Prakash ถูกต้องว่าคำประกาศเหมือนกันแม้ว่าคำอธิบายเพิ่มเติมเล็กน้อยเกี่ยวกับตัวชี้กรณีอาจเป็นไปตามลำดับ
"const int * p" เป็นตัวชี้ไปยัง int ที่ไม่อนุญาตให้เปลี่ยน int ผ่านตัวชี้นั้น "int * const p" เป็นตัวชี้ไปยัง int ที่ไม่สามารถเปลี่ยนให้ชี้ไปที่ int อื่นได้
ดูhttps://isocpp.org/wiki/faq/const-correctness#const-ptr-vs-ptr-const
const int
จะเหมือนกับint const
เช่นเดียวกับที่เป็นจริงกับประเภทสเกลาร์ทั้งหมดใน C โดยทั่วไปการประกาศพารามิเตอร์ฟังก์ชันสเกลาร์ตามที่const
ไม่ต้องการเนื่องจากความหมายของการเรียกตามค่าของ C หมายความว่าการเปลี่ยนแปลงใด ๆ ในตัวแปรจะเป็นแบบโลคัลสำหรับฟังก์ชันการปิดล้อม
นี่ไม่ใช่คำตอบโดยตรง แต่เป็นเคล็ดลับที่เกี่ยวข้อง เพื่อให้สิ่งต่างๆตรงฉันมักจะใช้การพาความร้อน "วางconst
ด้านนอก" โดยที่ "นอก" ฉันหมายถึงด้านซ้ายสุดหรือขวาสุด วิธีนี้จะไม่มีความสับสน - const ใช้กับสิ่งที่ใกล้เคียงที่สุด (ไม่ว่าจะเป็นประเภทหรือ*
) เช่น,
int * const foo = ...; // Pointer cannot change, pointed to value can change
const int * bar = ...; // Pointer can change, pointed to value cannot change
int * baz = ...; // Pointer can change, pointed to value can change
const int * const qux = ...; // Pointer cannot change, pointed to value cannot change
เหมือนกัน แต่ใน C ++ มีเหตุผลที่ดีที่จะใช้ const ทางด้านขวาเสมอ คุณจะสอดคล้องกันทุกที่เพราะต้องประกาศฟังก์ชันสมาชิก const ด้วยวิธีนี้:
int getInt() const;
มันเปลี่ยนแปลงthis
ตัวชี้ในการทำงานจากการFoo * const
ดูที่นี่.Foo const * const
ใช่พวกเขาเหมือนกันเพียง int
และแตกต่างกันสำหรับ int*
ฉันคิดว่าในกรณีนี้มันเหมือนกัน แต่นี่คือตัวอย่างที่คำสั่งมีความสำคัญ:
const int* cantChangeTheData;
int* const cantChangeTheAddress;