这是对这个问题的跟进.
如答案评论中所述:
内联变量具有以下属性: - 在每个转换单元中具有相同的地址.[...]通常您通过在cpp文件中定义变量来实现这一点,但是使用内联说明符,您只需在头文件中声明/定义变量,并且使用此内联变量的每个转换单元都使用完全相同的对象.
而且,从答案本身来说:
虽然该语言不保证(甚至提及)在跨共享库边界使用此新功能时会发生什么,但它确实可以在我的计算机上运行.
换句话说,当涉及共享库时,不清楚内联变量是否保证跨边界是唯一的.有人在经验证明它可以在某些平台上运行,但它不是一个正确的答案,它可能只是破坏其他平台上的一切.
内联变量在跨越边界使用时是否有任何保证,或者它只是一个我不应该依赖的实现细节?
为什么cppreference定义type_traits xxx_v快捷方式inline constexpr而不仅仅是constexpr?
例如,请参阅is_integral_v:
template< class T >
inline constexpr bool is_integral_v = is_integral<T>::value;
Run Code Online (Sandbox Code Playgroud)
这只是风格问题还是行为有所不同?据我所知,constexpr变量是隐含的inline.
编辑:查看最新标准的草案,它也使用inline constexpr.那么问题实际上适用于标准.
我知道这个问题已经被问过很多次了,但这似乎是一个略有不同的变化,我无法弄清楚。
考虑以下代码:
#include <cstdio>
struct TestValue;
inline const TestValue* v_ptr = nullptr;
struct TestValue {
static const TestValue v1;
TestValue() {
v_ptr = this;
printf("TestValue Initialized at %p\n", this);
}
};
struct CallTest {
CallTest() {
printf("CallTest Initalized at %p\n", this);
printf("v_ptr = %p\n", v_ptr);
}
};
const inline TestValue TestValue::v1{};
const inline CallTest ct{};
int main() {}
Run Code Online (Sandbox Code Playgroud)
我使用的是 C++17 或更高版本,它增加了对外部静态初始化内联变量的支持。我试图理解使用内联说明符“out of line”时围绕初始化顺序的保证。请注意, v1被声明为 TestValue 的静态变量,然后稍后但在 之前内联定义ct。令人惊讶的是(至少对我来说),使用 Clang 14.0.3,程序打印:
CallTest Initalized at 0x404059
v_ptr = (nil)
TestValue …Run Code Online (Sandbox Code Playgroud) c++ inline static-variables initialization-order inline-variable
我正在玩自动模板参数,我很惊讶这段代码没有编译:
constexpr auto bar = 2;
template<auto& T>
struct Foo {
auto operator()() const { return T; }
};
int main() {
Foo<bar> b;
b();
}
Run Code Online (Sandbox Code Playgroud)
Visual Studio 15.7(预览4)吐出这些错误:
Run Code Online (Sandbox Code Playgroud)error C2970: 'Foo': template parameter 'T': 'bar': an expression involving objects with internal linkage cannot be used as a non-type argument note: see declaration of 'Foo' note: see declaration of 'bar' error C2440: 'specialization': cannot convert from 'int' to 'int &' note: see reference to class template instantiation 'Foo<0>' …
C++14 添加了变量模板,它定义了相关变量组。在标准库中,变量模板用于访问每个类型特征的值成员:
template<class T>
inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
Run Code Online (Sandbox Code Playgroud)
C++17 添加了内联变量以更好地支持仅头文件库,这些库可以包含在同一应用程序内的多个源文件中(不同的翻译单元中允许相同的内联变量定义)。但就变量模板而言,无论如何它们都可以在程序中具有多个定义。那么,如果变量模板已经免于 ODR,还有什么理由将它们声明为内联呢?
只要很多人都关注constexpr差异inline constexpr,这是另一个有趣的问题,我就想忽略constexpr这次讨论的目的。
template <typename T>
bool myVar = sizeof(T) > 1;
Run Code Online (Sandbox Code Playgroud)
它与以下内容有何不同:
template <typename T>
inline bool myVar = sizeof(T) > 1;
Run Code Online (Sandbox Code Playgroud) C++20 引入了标准库头文件<numbers>,在命名空间中定义std::numbers了数学常量,例如sqrt2和sqrt3。它提供像inv_sqrt3,但不是inv_sqrt2。为什么inv_sqrt2不见了?
如果表达式的类型不依赖,但我们用它来初始化静态自动变量会发生什么?GCC和Clang的行为不同
template<typename T>
struct A {
static inline auto x = sizeof(T{}.f);
};
A<int> a;
Run Code Online (Sandbox Code Playgroud)
GCC不会引发错误.但Clang认为这是无效的,因为它实例化了"sizeof"的操作数.GCC似乎跳过了那一步因为sizeof(T{}.f)总是有类型size_t(不依赖于类型),所以它已经知道x没有实例化的类型.如果我们参考x,例如,两个编译器都会顺从拒绝该程序(void) a.x;.
它甚至必须解决这种类型x吗?使用C++ 14向上语言允许将事物(如函数)保留为"占位符类型"并进行延迟实例化以便稍后查找实际返回类型,如果我没记错的话.它是否也必须应用于此x,所以保持x占位符类型直到我们提到a.x?
根据标准,什么编译器是正确的?
编辑
有人问道
嗯,不应该这相当于此吗?
Run Code Online (Sandbox Code Playgroud)template<typename T> struct A { static const std::size_t x; }; template<typename T> inline constexpr std::size_t A<T>::x = sizeof(T{}.f);
在我的问题中,差异以及我关注的是我的问题中的静态数据成员auto.因此,为了知道类型x,您需要知道初始化程序的类型.Clang似乎急切地实例化初始化程序以获得类型.但海湾合作委员会显然没有?我想了解发生了什么.
C++ 标准(至少早于 C++17)已经说明了初始化顺序。
在同一翻译单元的命名空间范围内定义并动态初始化的静态存储持续时间的对象应按照其定义在翻译单元中出现的顺序进行初始化。
C++17 引入了内联变量,我相信这意味着可以在多个翻译单元中定义具有静态存储持续时间和命名空间范围以及动态初始化的单个变量。
C++ 是否对这些变量的初始化顺序做出任何保证?
Here is a header file containing an inline variable:
// inline.hpp
#pragma once
#include <iostream>
struct Test {
~Test() { std::cout << "deleted" << std::endl; }
};
inline const Test test;
Run Code Online (Sandbox Code Playgroud)
...included into two .cpp files:
// usage.cpp
#include "inline.hpp"
Run Code Online (Sandbox Code Playgroud)
// main.cpp
#include "inline.hpp"
auto main() -> int { return 0; }
Run Code Online (Sandbox Code Playgroud)
This program prints "deleted" twice which is unexpected. I thought there was only a single instance of every inline variable, so I was expecting only one "deleted".
Is …
应用于变量时inline说明符和关键字有什么区别?extern
C++ 17引入了内联变量,并且可以使用初始化程序在类定义中定义内联静态数据成员.它不需要一个类外的定义.例如,
struct X {
inline static int n = 1;
};
Run Code Online (Sandbox Code Playgroud)
鉴于此,我认为没有理由不总是使用内联静态数据成员,以获得简洁的语法.这样做的任何陷阱?请注意,我不介意慢速编译.