我有这个问题,我之前想过这个问题,但认为回答并非易事
int x = x + 1;
int main() {
return x;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果程序的行为是有效的,那么它是否被定义或未定义.如果定义了,那么x已知的值是main多少?
当我在C++中使用静态变量时,我常常想要初始化一个变量,将另一个变量传递给它的构造函数.换句话说,我想创建彼此依赖的静态实例.
在单个.cpp或.h文件中,这不是问题:将按照声明的顺序创建实例.但是,如果要使用另一个编译单元中的实例初始化静态实例,则无法指定顺序.结果是,根据天气,可能会发生构建依赖于另一个实例的实例,并且之后才构建另一个实例.结果是第一个实例初始化不正确.
有谁知道如何确保以正确的顺序创建静态对象?我已经搜索了很长时间寻找解决方案,尝试了所有这些解决方案(包括Schwarz Counter解决方案),但我开始怀疑有一个确实有效.
一种可能性是使用静态函数成员的技巧:
Type& globalObject()
{
static Type theOneAndOnlyInstance;
return theOneAndOnlyInstance;
}
Run Code Online (Sandbox Code Playgroud)
实际上,这确实有效.遗憾的是,您必须编写globalObject().MemberFunction()而不是globalObject.MemberFunction(),从而导致一些令人困惑和不雅的客户端代码.
更新:感谢您的反应.遗憾的是,我确实似乎回答了自己的问题.我想我必须学会忍受它......
c++ static-variables initialization-order static-order-fiasco
考虑:
int f () {
static int i = 0;
return i++;
}
struct Test {
int a, b;
Test () : a(f()), b(f()) {}
};
Test t;
Run Code Online (Sandbox Code Playgroud)
我知道a之前b由于其声明的顺序而被初始化struct.
我也知道这两次打电话都没有f参加g(f(), f()).
所以我想知道是否保证t.a == 0和t.b == 1?
c++ operator-precedence undefined-behavior initialization-order language-lawyer
我知道在 C++ 中,类头中成员的声明定义了初始化顺序。你能告诉我为什么 C++ 选择这种设计吗?强制初始化顺序而不是遵循初始化列表有什么好处吗?
我对C++中的构造和初始化顺序保证有些怀疑.例如,下面的代码有四个班X,Y,Z和W.main函数实例化一个对象class X,该对象包含一个对象class Y,并从中派生出来class Z,因此将调用两个构造函数.另外,const char*传递给X构造函数的参数将被隐式转换为对象class W,因此W也必须调用构造函数.
C++标准对复制构造函数的调用顺序有什么保证?或者,等效地,该程序可以打印什么?
#include <iostream>
class Z {
public:
Z() { std::cout << "Z" << std::endl; }
};
class Y {
public:
Y() { std::cout << "Y" << std::endl; }
};
class W {
public:
W(const char*) { std::cout << "W" << std::endl; }
};
class X : public Z {
public:
X(const W&) …Run Code Online (Sandbox Code Playgroud) 我正在为分散式模块注册寻找一个好的解决方案.
我不想要一个使用项目所有模块单元的单元,但我宁愿让模块单元自己注册.
我能想到的唯一解决方案就是依赖initializationDelphi单元.
我写了一个测试项目:
单元2
TForm2 = class(TForm)
private
class var FModules: TDictionary<string, TFormClass>;
public
class property Modules: TDictionary<string, TFormClass> read FModules;
procedure Run(const AName: string);
end;
procedure TForm2.Run(const AName: string);
begin
FModules[AName].Create(Self).ShowModal;
end;
initialization
TForm2.FModules := TDictionary<string, TFormClass>.Create;
finalization
TForm2.FModules.Free;
Run Code Online (Sandbox Code Playgroud)
UNIT3
TForm3 = class(TForm)
implementation
uses
Unit2;
initialization
TForm2.Modules.Add('Form3', TForm3);
Run Code Online (Sandbox Code Playgroud)
UNIT4
TForm4 = class(TForm)
implementation
uses
Unit2;
initialization
TForm2.Modules.Add('Form4', TForm4);
Run Code Online (Sandbox Code Playgroud)
这有一个缺点.是否保证我的注册单元(在本例中为Unit2s)initialization部分始终先运行?
我经常阅读关于initialization部分的警告,我知道我必须避免在其中引发异常.
我知道这个问题已经被问过很多次了,但这似乎是一个略有不同的变化,我无法弄清楚。
考虑以下代码:
#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
cppreference说std::atexit:
这些函数可以与具有静态存储持续时间的对象的销毁同时被调用,并且保持如果在B的注册之前如果A的注册被排序,则在调用之前对B的调用进行排序的保证. A,同样适用于静态对象构造函数和对atexit的调用之间的顺序
我理解这一段意味着,如果std::atexit在静态初始化期间调用,则在静态对象的销毁过程中,在静态对象被破坏之前调用已注册的函数,该静态对象std::atexit在调用注册函数时被最后初始化.我还解释"可以同时调用"意味着调用可以发生在静态对象析构之间,而不是对单词的多线程解释.
我想知道的是,当初始化开始或完成时,对象是否被视为已初始化(在此排序的上下文中).我写了一个简短的测试来测试这个:
#include <cstdlib>
#include <iostream>
struct foo
{
foo()
{
std::cout << "ctor\n";
std::atexit([]() { std::cout << "atexit\n"; });
}
~foo()
{
std::cout << "dtor\n";
}
};
foo my_foo;
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是(http://cpp.sh/3bllu):
ctor
dtor
atexit
Run Code Online (Sandbox Code Playgroud)
这使我相信,my_foo在构建完成之前,不会在这种情况下初始化.换句话说,该函数被认为在my_foo初始化之前已经注册,因此注册函数在my_foo销毁之后执行.
我似乎找不到任何可以保证这种行为的东西,我甚至不完全确定我对引用段落的初步解释是正确的.我描述的行为是我可以依赖的,还是实现定义甚至未定义的行为?
c++ atexit initialization-order static-initialization language-lawyer
以下代码
#include <iostream>
struct A {
A() {
std::cout << std::endl;
}
};
struct B {
static inline A a;
};
int main() {
}
Run Code Online (Sandbox Code Playgroud)
用gcc 编译后成功,但用clang 编译后因分段错误而崩溃。代码不标准还是叮当错了?
在我研究在C#中构建Singleton的最佳方法的过程中,我偶然发现了以下文章,其中简要提及在C++中
"C++规范在静态变量的初始化顺序方面留下了一些模糊性."
我最终寻找到这个问题,并发现这个和这个.基本上(据我所知),C++中静态变量的初始化顺序是未定义的.好吧,我想到目前为止这么好,但后来我想了解文章后面的说法
"幸运的是,.NET Framework通过处理变量初始化来解决这种歧义."
所以我发现他们说的这个页面
类的静态字段变量初始值设定项对应于以它们出现在类声明中的文本顺序执行的赋值序列.
并举例说明
using System;
class Test
{
static void Main() {
Console.WriteLine("{0} {1}", B.Y, A.X);
}
public static int F(string s) {
Console.WriteLine(s);
return 1;
}
}
class A
{
static A() {}
public static int X = Test.F("Init A");
}
class B
{
static B() {}
public static int Y = Test.F("Init B");
}
the output must be:
Init B
Init A
1 1
Run Code Online (Sandbox Code Playgroud)
"因为静态构造函数执行时的规则(如第10.11节所定义)规定B的静态构造函数(以及因此B的静态字段初始化程序)必须在A的静态构造函数和字段初始化程序之前运行." …
c++ ×9
c# ×2
.net ×1
atexit ×1
clang ×1
constructor ×1
delphi ×1
delphi-units ×1
delphi-xe3 ×1
inline ×1
module ×1