ตัวอย่างที่รันได้น้อยที่สุด
คุณลักษณะ C ++ 17 ที่ยอดเยี่ยมนี้ช่วยให้เราสามารถ:
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
inline constexpr int notmain_i = 42;
const int* notmain_func();
#endif
notmain.cpp
#include "notmain.hpp"
const int* notmain_func() {
return ¬main_i;
}
รวบรวมและเรียกใช้:
g++ -c -o notmain.o -std=c++17 -Wall -Wextra -pedantic notmain.cpp
g++ -c -o main.o -std=c++17 -Wall -Wextra -pedantic main.cpp
g++ -o main -std=c++17 -Wall -Wextra -pedantic main.o notmain.o
./main
GitHub อัปสตรีม
ดูเพิ่มเติม: ตัวแปรอินไลน์ทำงานอย่างไร
มาตรฐาน C ++ สำหรับตัวแปรอินไลน์
มาตรฐาน C ++ รับประกันว่าที่อยู่จะเหมือนกัน C ++ 17 N4659 ร่างมาตรฐาน
10.1.6 "ตัวระบุอินไลน์":
6 ฟังก์ชันอินไลน์หรือตัวแปรที่มีการเชื่อมโยงภายนอกต้องมีที่อยู่เดียวกันในทุกหน่วยการแปล
cppreference https://en.cppreference.com/w/cpp/language/inlineอธิบายว่าหากstatic
ไม่ได้รับแสดงว่ามีการเชื่อมโยงภายนอก
การใช้งานตัวแปรแบบอินไลน์ของ GCC
เราสามารถสังเกตวิธีการใช้งานได้ด้วย:
nm main.o notmain.o
ซึ่งประกอบด้วย:
main.o:
U _GLOBAL_OFFSET_TABLE_
U _Z12notmain_funcv
0000000000000028 r _ZZ4mainE19__PRETTY_FUNCTION__
U __assert_fail
0000000000000000 T main
0000000000000000 u notmain_i
notmain.o:
0000000000000000 T _Z12notmain_funcv
0000000000000000 u notmain_i
และman nm
พูดเกี่ยวกับu
:
"u" สัญลักษณ์นี้เป็นสัญลักษณ์สากลที่เป็นเอกลักษณ์ นี่คือส่วนขยาย GNU ของชุดมาตรฐานของการผูกสัญลักษณ์ ELF สำหรับสัญลักษณ์ดังกล่าวตัวเชื่อมโยงแบบไดนามิกจะตรวจสอบให้แน่ใจว่าในกระบวนการทั้งหมดมีเพียงสัญลักษณ์เดียวที่มีชื่อนี้และพิมพ์ที่ใช้
ดังนั้นเราจึงเห็นว่ามีส่วนขยาย ELF สำหรับสิ่งนี้โดยเฉพาะ
ก่อน C ++ 17: extern const
ก่อน C ++ 17 และใน C เราสามารถบรรลุผลที่คล้ายกันมากกับ an extern const
ซึ่งจะนำไปสู่การใช้ตำแหน่งหน่วยความจำเดียว
ข้อเสียinline
คือ:
- มันเป็นไปไม่ได้ที่จะสร้างตัวแปร
constexpr
ด้วยเทคนิคนี้inline
อนุญาตให้ทำได้เท่านั้น: จะประกาศ constexpr extern ได้อย่างไร?
- มีความสง่างามน้อยกว่าเนื่องจากคุณต้องประกาศและกำหนดตัวแปรแยกกันในไฟล์ header และ cpp
main.cpp
#include <cassert>
#include "notmain.hpp"
int main() {
// Both files see the same memory address.
assert(¬main_i == notmain_func());
assert(notmain_i == 42);
}
notmain.cpp
#include "notmain.hpp"
const int notmain_i = 42;
const int* notmain_func() {
return ¬main_i;
}
notmain.hpp
#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP
extern const int notmain_i;
const int* notmain_func();
#endif
GitHub อัปสตรีม
Pre-C ++ 17 ส่วนหัวทางเลือกเท่านั้น
สิ่งเหล่านี้ไม่ดีเท่าextern
วิธีแก้ปัญหา แต่ใช้งานได้และใช้ตำแหน่งหน่วยความจำเดียวเท่านั้น:
constexpr
ฟังก์ชั่นเพราะconstexpr
หมายถึงinline
และinline
ช่วย (กองกำลัง) คำนิยามที่ปรากฏในหน่วยการแปลทุก :
constexpr int shared_inline_constexpr() { return 42; }
และฉันพนันได้เลยว่าคอมไพเลอร์ที่เหมาะสมจะอินไลน์
คุณยังสามารถใช้ตัวแปรจำนวนเต็มconst
หรือconstexpr
คงที่ใน:
#include <iostream>
struct MyClass {
static constexpr int i = 42;
};
int main() {
std::cout << MyClass::i << std::endl;
// undefined reference to `MyClass::i'
//std::cout << &MyClass::i << std::endl;
}
แต่คุณไม่สามารถทำสิ่งต่างๆได้เช่นการรับที่อยู่มิฉะนั้นจะกลายเป็นสิ่งที่ใช้ไม่ได้โปรดดู: https://en.cppreference.com/w/cpp/language/static "Constant static members" และการกำหนดข้อมูลคงที่ constexpr สมาชิก
ค
ใน C สถานการณ์จะเหมือนกับ C ++ ก่อน C ++ 17 ฉันได้อัปโหลดตัวอย่างที่: "คงที่" หมายความว่าอะไรใน C?
ข้อแตกต่างเพียงอย่างเดียวก็คือใน C ++ มีconst
ความหมายstatic
สำหรับ globals แต่ไม่ได้อยู่ในความหมายของ C: C ++ ของ "static const" เทียบกับ "const"
มีวิธีใดที่จะอินไลน์ได้อย่างเต็มที่?
สิ่งที่ต้องทำ: มีวิธีใดบ้างในการแทรกตัวแปรโดยไม่ต้องใช้หน่วยความจำเลย?
เหมือนกับสิ่งที่พรีโปรเซสเซอร์ทำ
สิ่งนี้จะต้องมี:
- ห้ามหรือตรวจจับว่ามีการใช้แอดเดรสของตัวแปรหรือไม่
- เพิ่มข้อมูลนั้นในไฟล์ออบเจ็กต์ ELF และปล่อยให้ LTO ปรับให้เหมาะสม
ที่เกี่ยวข้อง:
ทดสอบใน Ubuntu 18.10, GCC 8.2.0
const
ปกตินี้จะใช้ได้เฉพาะถ้าตัวแปรคือ