C++中的静态变量构造

3
编译器如何知道如何正确处理这段代码?
struct Foo
{
    int bar;

    Foo()
    {
        bar = 3;
    }

    Foo& operator=(const Foo& other)
    {
        bar = other.bar;
        return *this;
    }

    int SetBar(int newBar)
    {
        return bar = newBar;
    }
};

static Foo baz;
static Foo someOtherBaz = baz;
static int placeholder = baz.SetBar(4);
someOtherBaz.bar 的最终值将是什么?
1个回答

10

someOtherBaz.bar的值为3。

在翻译单元(TU)中,静态对象的构造顺序是按它们出现的顺序进行的(请注意,不同翻译单元中的静态对象没有定义的顺序)。

  1. 首先,使用默认构造函数构造了baz。这将把baz.bar设置为3。
  2. 接下来,通过复制构造函数构造了someOtherBaz。由于未定义复制构造函数,将使用默认复制构造函数,它只会复制每个字段。因此someOtherBaz.bar将被赋值为3。
  3. 最后,要构造placeholder,将调用baz.SetBar,这也将更改baz的值(但不会更改someOtherBaz的值,因为它们是独立的对象;虽然您基于baz的值创建了someOtherBaz,但它们是不同的对象,可以独立地更改)。

因此,在最后,您将得到:

 baz.bar: 4
 someOtherBaz.bar: 3
 placeholder: 4

1
@legends2k - 对于单个参数的构造函数,TYPE t = argTYPE t(arg) 是相同的。 - R Samuel Klatchko
2
@legend22K - 代码中并不存在赋值操作 - 使用 = 符号并非赋值,而是复制构造函数的调用。 - anon
@Neil:哦,谢谢,现在清楚了!如果它调用的是复制构造函数而不是赋值操作,在这种情况下如果它是一个无参构造函数,那么如果只有一个构造函数需要传入两个参数呢?Samuel 是指单参数构造函数还是无参数构造函数? - legends2k
我猜这个会导致一个“静态初始化惨案”(http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13);或许Neil或Samuel能在这里给我们一些启发。 - legends2k
1
@wowus - 不同翻译单元中的全局对象初始化之间没有定义的顺序。因此,如果您有 extern Foo f1; Foo f2 = f1;,则可以从f1的原始未初始化内存初始化f2。 - R Samuel Klatchko
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接