C++ 中的静态初始化顺序问题

发布于 2024-09-25 15:12:35 字数 1492 浏览 9 评论 0原文

这是旧主题的另一个变体:初始化顺序 不同翻译单元中的静态对象没有定义。

下面是我的特定场景的精简示例。这 G 类和 F 类是非 POD 类型。 F 依赖于 G 的意义是 构造 F 的实例,您需要一定数量的实例 G.(例如,F 可能是应用程序发出的某些消息,并且 G 的实例将成为此类消息的组成部分。)

G.hpp

#ifndef G_HPP
#define G_HPP

struct G
{
    G() {} // ...
};

inline G operator+(G, G) { return G(); }

#endif

Gs.hpp

#ifndef GS_HPP
#define GS_HPP

#include "G.hpp"

extern const G g1;
extern const G g2;
extern const G g3;
extern const G g4;
extern const G g5;
extern const G g6;
extern const G g7;
extern const G g8;
extern const G g9;

#endif

Gs.cpp

#include "Gs.hpp"

const G g1;
const G g2;
const G g3;
const G g4;
const G g5;
const G g6;
const G g7;
const G g8;
const G g9;

F.hpp

#ifndef F_HPP
#define F_HPP

#include "G.hpp"

struct F
{
    F(G) {} // ...
};

#endif

Fs.hpp

#ifndef FS_HPP
#define FS_HPP

#include "F.hpp"

extern const F f1;
extern const F f2;
extern const F f3;

#endif

Fs.cpp

#include "Fs.hpp"
#include "Gs.hpp"

const F f1(g1 + g2 + g3);
const F f2(g4 + g5 + g6);
const F f3(g7 + g8 + g9);

F 的构造函数采用一个参数,该参数是应用 operator+ 到 G 的实例。由于 F 和 G 的实例都是 全局变量,不能保证 G 的实例具有 当 F 的构造函数需要它们时被初始化。

这里的特殊性是,整个过程中有很多 G 和 F。 地方,我想保持语法尽可能接近 到上面发布的代码,同时仍然强制构建 每当 F 需要 G 时。

This is another variation of an old theme: The initialization order of
static objects in different translation units is not defined.

Below is a stripped-down example of my particular scenario. The
classes G and F are non-POD types. F depends on G is the sense that to
construct an instance of F you need some number of instances of
G. (For example, F could be some message an application emits, and
instances of G would be components of such messages.)

G.hpp

#ifndef G_HPP
#define G_HPP

struct G
{
    G() {} // ...
};

inline G operator+(G, G) { return G(); }

#endif

Gs.hpp

#ifndef GS_HPP
#define GS_HPP

#include "G.hpp"

extern const G g1;
extern const G g2;
extern const G g3;
extern const G g4;
extern const G g5;
extern const G g6;
extern const G g7;
extern const G g8;
extern const G g9;

#endif

Gs.cpp

#include "Gs.hpp"

const G g1;
const G g2;
const G g3;
const G g4;
const G g5;
const G g6;
const G g7;
const G g8;
const G g9;

F.hpp

#ifndef F_HPP
#define F_HPP

#include "G.hpp"

struct F
{
    F(G) {} // ...
};

#endif

Fs.hpp

#ifndef FS_HPP
#define FS_HPP

#include "F.hpp"

extern const F f1;
extern const F f2;
extern const F f3;

#endif

Fs.cpp

#include "Fs.hpp"
#include "Gs.hpp"

const F f1(g1 + g2 + g3);
const F f2(g4 + g5 + g6);
const F f3(g7 + g8 + g9);

F's constructor takes an argument which is the result of applying
operator+ to instances of G. Since the instances of both F and G are
global variables, there is not guarantee that the instances of G have
been initialized when the constructor of F needs them.

The particularity here is that there are many Gs and Fs all over the
place, and I would like to keep the syntax as much as possibly close
to the code posted above, while still enforcing the construction of a
G whenever an F needs it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

王权女流氓 2024-10-02 15:12:35

来自 http://www.parashift.com/c++-faq- lite/ctors.html#faq-10.15

将全局对象更改为在首次使用时构造对象的函数。

// Gs.hpp
const G & g1();

// Gs.cpp
const G & g1() {
  static const G* g1_ptr = new G();
  return *g1_ptr;
}

// Fs.cpp
const F & f1() {
  static const F* f1_ptr = new F(g1() + g2() + g3());
  return *f1_ptr;
}

或者,如果您确实无法忍受添加额外的 (),请使用一些 #define 来隐藏它们:

// Gs.hpp
const G & get_g1();
#define g1 (get_g1())
// Definition of get_g1() like g1() from prev. example

From http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15 .

Change your global objects into functions which construct the object on first use.

// Gs.hpp
const G & g1();

// Gs.cpp
const G & g1() {
  static const G* g1_ptr = new G();
  return *g1_ptr;
}

// Fs.cpp
const F & f1() {
  static const F* f1_ptr = new F(g1() + g2() + g3());
  return *f1_ptr;
}

Or if you really can't stand adding the extra ()s, use some #defines to hide them:

// Gs.hpp
const G & get_g1();
#define g1 (get_g1())
// Definition of get_g1() like g1() from prev. example
野味少女 2024-10-02 15:12:35

将外部声明保留在标题中。将所有 fNgN 定义按适当的顺序放入单个 cpp 文件中。

Keep the extern declarations in the headers. Put all the fN and gN definitions into a single cpp file in the appropriate order.

淡忘如思 2024-10-02 15:12:35

也许类似于用于初始化 cin 和朋友的文件缓冲区的技巧对您有用? (仔细阅读。)

Maybe a trick similar to the one used to initialize cin and friends' filebuffers would work for you? (Read <iostream> carefully.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文