简体   繁体   English

c++ 在调用其构造函数之前访问静态/全局对象的成员是否有效?

[英]c++ is it valid to access members of static/global object before its constructor has been called?

Is it valid and well defined (not asking whether it's pretty) to call member functions of an object in global namespace before this object's constructor has been executed (for example from a global new replacement) - and when this member function executes, are the member variables of that object guaranteed to be zero initialized and is it no error to access (and even write to) them?在执行此对象的构造函数之前(例如从全局新替换)调用全局命名空间中对象的成员函数是否有效且定义明确(不问它是否漂亮) - 当该成员函数执行时,成员是该对象的变量保证为零初始化并且访问(甚至写入)它们没有错误吗? for example:例如:

#include <iostream>
#include <memory>

using namespace std;

struct A {
  A() {
    new int();
  }
};

A a_;

struct B {
  B() : var(10) {
  }
  void print() {
    printf("var is %d\n", var);
    var = 5;
  }
  int var;
};

B b_;

void* operator new(size_t bytes) {
    b_.print();
    b_.print();
    return malloc(bytes);
}

int main()
{
    b_.print();
    return 0;
}

this compiles and prints这编译并打印

var is 0
var is 5
var is 10

but is it defined behaviour?但它是定义的行为吗?

It is true that zero-initialization happens up front, but it is undefined behavior to invoke non-static class methods before their class instance is constructed.确实,零初始化是预先发生的,但在构造类实例之前调用非静态类方法是未定义的行为。 The method call itself becomes undefined behavior.方法调用本身变成未定义的行为。

Objects in global (static) scope that are defined in the same translation unit are constructed in their declaration order (and destroyed in the opposite order).在同一翻译单元中定义的全局(静态)范围内的对象按其声明顺序构造(并按相反顺序销毁)。

Here, a_ gets constructed first, and then ends up invoking the new overload, which invokes a method of a class instance that has not been constructed yet, which is undefined behavior.在这里, a_首先被构造,然后最终调用new重载,它调用尚未构造的类实例的方法,这是未定义的行为。

And if the two objects get defined in different translation units you end up with the static initialization order fiasco .如果这两个对象在不同的​​翻译单元中定义,你最终会得到静态初始化顺序 fiasco

Even if you define b_ first, this is still undefined behavior unless you can guarantee that nothing in any other translation unit ends up calling this new overload.即使您首先定义了b_ ,这仍然是未定义的行为,除非您可以保证任何其他翻译单元中的任何内容都不会调用这个new重载。 This includes the C++ library.这包括 C++ 库。 Many C++ implementations' library do allocate some storage for their own use, so this is fairly likely to be undefined behavior as well, in the end, even if the definition order gets reversed, here.许多 C++ 实现的库确实为自己的使用分配了一些存储空间,因此这也很可能是未定义的行为,最终,即使定义顺序在这里颠倒了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM