我有一个关于全局变量如何在c++中工作的问题。
我知道全局变量是邪恶的,所以这不是这个问题的重点。我只想对以下示例中发生的事情有更深入的了解。

#include <cstdint>
#include <iostream>
#include <vector>

class B
{
public:
  B();
  ~B();
private:
  static std::vector<int32_t> v_;
};

B::B()
{
  std::cout << "v_.size() = " << v_.size() << std::endl;
  for (auto i : v_)
    std::cout << i << std::endl;
}

B::~B()
{
  std::cout << "v_.size() = " << v_.size() << std::endl;
  std::cout << "v_[0] = " << v_[0] << std::endl;
  std::cout << "v_.at(0) = " << v_.at(0) << std::endl;
  for (auto i : v_)
    std::cout << i << std::endl;
}

B b;

std::vector<int32_t> B::v_ { 5, -7 };

int main()
{
  return 0;
}

给出以下输出:
$ ./test
v_.size() = 0
v_.size() = 2
v_[0] = 0
v_.at(0) = 0
0
0

为什么B的析构函数中 vector 的大小仍为2?

当我访问 vector 的元素时,我得到了随机内存,这是我理解的,因为 vector 在B之前被清理了。但是对我来说, vector 的大小应该为0甚至更好,在请求时抛出某种错误尺寸。即使使用at()函数也不会引发错误,因为大小仍然为2。

我也知道我可以通过切换b和 vector 的初始化来解决此问题。我的问题更多是为什么这个特定的示例不会引发某种错误,而我认为应该如此。

注意:就像我的评论一样,为什么此行为属于未定义行为,而不是因为该点不存在 vector 而读取或写入非法的内存位置?我当时以为这会/应该产生段错误,但我不明白为什么它不会

最佳答案

未定义行为表示C++标准未定义程序的行为。合格的C++编译器可以使用具有此功能的程序对进行任何操作,或者表现出未定义的行为(是的,UB可以进行时间旅行)。

v_中构造程序之前,通过将B::B作为对象访问,您的程序表现出未定义的行为。既然这样做,C++标准就不会指定或限制程序执行。

在这种情况下,编译器将UB访问视为正在访问空std::vector。这是有效的,因为任何东西都是有效的。如果您没有完成UB(上述症状除外),该程序将继续进行,这也是有效的选择。

如果我们设想移除ctr中的UB,则在销毁过程中,您的程序将再次显示UB。这次通过销毁v_作为vector对象来访问它。同样,通过此操作,在UB之前,之后和之后,程序的行为不受C++标准的定义或约束。

在这种情况下,它的行为就好像您有一个2个值的 vector ,其值均为0。这是符合的,因为符合

许多可能性之一是数据在堆上被回收,但是指针悬空了。将 vector 的“旋转”数据视为指针时,它们仍将2 sizeof(int)分开,而.size()则将其指向2。但是,指向的数据已在堆上回收,并且那里有不同的数据。

关于c++ - C++理解清除后访问全局变量不会产生某种错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53745137/

10-11 15:16
查看更多