[英]How is the inline specifier used in C++ to preserve the one definition rule?
我一直在試圖弄清楚inline
說明符如何保留 ODR。 到目前為止,我寫的所有內容似乎都沒有必要,因為包含保護確保定義只包含一次。
假設我在名為constants.h
的文件中有以下定義
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace constants {
inline const double pi { 3.14159255358979323846 };
inline const double e { 2.71828182845904523536 };
}
#endif
根據我對與 ODR 相關的inline
理解,編寫inline
說明符是為了確保這些常量的定義僅在多個翻譯單元中初始化一次。 因此,如果我將這個文件包含在a.cpp
和b.cpp
一切都應該很好。
現在,讓我們刪除inline
關鍵字。
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace constants {
const double pi { 3.14159255358979323846 };
const double e { 2.71828182845904523536 };
}
#endif
現在,如果我將其包含在a.cpp
和b.cpp
沒有問題。 我想這是因為包含警衛確保同一事物的多個定義不會出現兩次。
接下來,讓我們移除包含守衛
namespace constants {
const double pi { 3.14159255358979323846 };
const double e { 2.71828182845904523536 };
}
還是沒有問題。 可能是因為const
限定的變量定義默認具有內部鏈接。 因此,在a.cpp
和b.cpp
包含constants.h
使這些定義中的每一個都默認為各自的翻譯單元內部。
很難打破跨多個翻譯單元的 ODR。 現在讓我們刪除 const。
namespace constants {
double pi { 3.14159255358979323846 };
double e { 2.71828182845904523536 };
}
現在! ODR 跨越多個翻譯單元。 讓我們嘗試使用inline
修復此問題,以便編譯器知道只定義這些變量一次。
namespace constants {
inline double pi { 3.14159255358979323846 };
inline double e { 2.71828182845904523536 };
}
好的,沒有更多錯誤,這個文件可以再次包含在多個翻譯單元中。 那么為什么將頭文件中的常量聲明為inline
被認為是“最佳實踐”? 打破 ODR 似乎需要付出很多努力,並且在包含守衛的情況下inline
是多余的。
未使用說明符 extern 聲明的常量具有內部鏈接。
所以所有包含這些聲明的編譯單元
namespace constants {
const double pi { 3.14159255358979323846 };
const double e { 2.71828182845904523536 };
}
有自己的常數 pi 和 e。
來自 C++ 14 標准(3.5 程序和鏈接)
3 具有命名空間范圍 (3.3.6) 的名稱具有內部鏈接,如果它是
(3.2) — 非 volatile const 限定類型的變量,既未顯式聲明為 extern 也未先前聲明為具有外部鏈接; 或者
與上述聲明相反,這些聲明
namespace constants {
double pi { 3.14159255358979323846 };
double e { 2.71828182845904523536 };
}
有外部聯動。 因此,如果這些聲明(也是定義)包含在多個編譯單元中,則編譯器會發出錯誤消息,因為一個定義規則被破壞。
例如,如果您在未命名的命名空間中聲明它們,則可以使上述變量具有內部鏈接
namespace constants {
namespace {
double pi { 3.14159255358979323846 };
double e { 2.71828182845904523536 };
}
}
至於這些聲明
namespace constants {
inline double pi { 3.14159255358979323846 };
inline double e { 2.71828182845904523536 };
}
然后可以在多個編譯單元中定義具有外部鏈接的內聯變量。 此外,應在每個使用 ODR 的編譯單元中定義內聯變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.