考虑以下标题并假设它在多个TU中使用:
static int x = 0;
struct A {
A() {
++x;
printf("%d\n", x);
}
};
Run Code Online (Sandbox Code Playgroud)
正如这个问题所解释的那样,这是ODR违规,因此也就是UB.
现在,如果我们的函数引用非对象并且我们不在该函数中使用它(加上其他条款),则不存在ODR违规,因此这在头文件中仍然可以正常工作:inlinevolatile const
constexpr int x = 1;
struct A {
A() {
printf("%d\n", x);
}
};
Run Code Online (Sandbox Code Playgroud)
但如果我们确实碰巧使用它,我们又回到UB的第一个方面:
constexpr int x = 1;
struct A {
A() {
printf("%p\n", &x);
}
};
Run Code Online (Sandbox Code Playgroud)
因此,鉴于我们现在有inline变量,指南是否应该在标题中标记所有namespace变量inline以避免所有问题?
constexpr inline int x = 1;
struct A {
A() {
printf("%p\n", &x);
}
};
Run Code Online (Sandbox Code Playgroud)
这似乎也更容易教,因为我们可以简单地说" inline标题中的所有内容"(即函数和变量定义),以及"从不static …
当您在C++头文件中有一个静态全局变量时,包含头文件的每个翻译单元最终都会有自己的变量副本.
但是,如果我在同一个头文件中声明一个类,并创建该类的成员函数,在类声明中实现内联,它使用静态全局变量,例如:
#include <iostream>
static int n = 10;
class Foo {
public:
void print() { std::cout << n << std::endl; }
};
Run Code Online (Sandbox Code Playgroud)
然后我看到gcc 4.4下的一些奇怪的行为:
如果我在没有优化的情况下编译,则成员函数的所有使用都使用来自其中一个翻译单元(g ++命令行中提到的第一个)的变量副本.
如果我编译-O2,每次使用成员函数都使用来自翻译单元的变量的副本.
显然这是一个非常糟糕的设计,所以这个问题只是出于好奇.但是,我的问题是,C++标准对此案例的说法是什么?通过在启用和不启用优化的情况下提供不同的行为,g ++是否正常运行?
我想知道我是否可以在头文件中定义一些函数然后在同一个头文件中使用它们,同时将它们隐藏在其他任何东西中?
例如,我可以首先定义一些通用辅助函数(特定于数据结构),然后在使用这些函数的同一个头中定义一些数据结构吗?
例如:
template<class T>
void Swap(T &a, T &b)
{
T temp = a;
a = b;
b = temp;
}
Run Code Online (Sandbox Code Playgroud)
但我不想Swap()干涉其他具有相同名称的功能.
我可以把它变成一个私有方法,但是我必须为每个使用它的类提供相同的实现,或者让它们成为朋友类...
我在我的AI项目中遇到了一个有趣的问题.我正在尝试格式化一些调试文本,并且发生了一些奇怪的事情.这是一段代码:
float ratio = 1.0f / TIME_MOD;
Run Code Online (Sandbox Code Playgroud)
TIME_MOD是一个静态浮点数,在单独的文件中声明.这个值是基于另一个类中的用户输入修改的(我已经验证了值在"input"函数的范围内仍在调试时被更改),但每当我尝试在外部循环中除以它时,我得到了相同的号码.(1除以TIME_MOD的初始值).
我是否遗漏了有关静态变量和文件范围的内容?