我遇到的问题是,当初始化所有静态变量时,我在初始化时将元素推入向量,然后当它进入主函数时,向量重置为0,就像它已经清除一样。在我的例子中,向量处于不同的CPP中,但这也显示了问题:
#include <iostream>
#include <vector>
struct List
{
static std::vector<int> listVector;
};
struct Foo
{
Foo()
{
std::cout << List::listVector.size() << '\n'; // Prints 0
List::listVector.push_back(1);
std::cout << List::listVector.size() << '\n'; // Prints 1
}
};
Foo fooObj;
std::vector<int> List::listVector;
int main()
{
std::cout << List::listVector.size() << '\n'; // Prints 0
List::listVector.push_back(2);
std::cout << List::listVector.size() << '\n'; // Prints 1
}
我添加到矢量的第一个元素已丢失。我知道必须小心静态全局变量的初始化顺序,但我无法理解为什么向量被清除。我很想到,当Foo构造函数运行时,它会向向量添加一个元素,但尚未创建向量,因为它是在创建Foo对象后写入的。但是,如果是这种情况,那么当我在构造函数中执行此操作时,我添加的是什么向量,并且它打印出的大小为1?
我有点困惑。
答案 0 :(得分:3)
我很想到,当Foo构造函数运行时,它会向向量添加一个元素,但尚未创建向量,因为它是在创建Foo对象后写入的。
是的,这是完全正确的。 fooObj
构造函数只访问构造vector 的内存,但尚未构造它。 (因此程序具有未定义的行为,必须修复)
但是,如果是这种情况,那么当我在构造函数中执行此操作时,我添加的是什么向量,并且它打印出的大小为1?
编译器只是将内存解释为有效向量,因为它无法另外知道。这恰好工作,因为全局将被构造的内存最初为零,因为执行环境确保所有静态对象的内存最初为零,这恰好与默认构造状态相同(对于您实现的std::vector
)定义。程序无法知道包含全零的内存位置还不是有效的向量。
稍后,向量的构造函数运行,重新初始化内存,进入默认构造状态。
Here是一个示例,显示了您的程序的作用:将包含全零的原始内存解释为向量,并向该幻像向量添加元素(实际上并不存在),然后实际构造一个向量记忆。创建真实矢量后,添加到幻像矢量的任何内容都将丢失。
#include <iostream>
#include <vector>
int main()
{
// initialize a block of memory to zero:
alignas(std::vector<int>) char memory[sizeof(std::vector<int>)] = {};
// use that memory as a vector, even though we haven't created any vector
// (this is undefined behaviour! there is no vector yet!):
std::vector<int>& vec = *reinterpret_cast<std::vector<int>*>(memory);
vec.push_back(1);
// the non-existent "phantom vector" has size 1:
std::cout << vec.size() << std::endl;
// now use "placement new" to construct an empty vector in that memory:
new (memory) std::vector<int>();
// the real vector is empty, the element in the phantom vector is lost:
std::cout << vec.size() << std::endl;
}
要修复程序,您需要在任何引用它之前初始化向量(具体地说,在fooObj
构造函数尝试使用之前,通过在fooObj
之前定义它)。
答案 1 :(得分:1)
如果您将代码更改为
#include <iostream>
#include <vector>
namespace List
{
static std::vector<int> listVector;
}
struct Foo
{
Foo()
{
std::cout << List::listVector.size() << '\n'; // Prints 0
List::listVector.push_back(1);
std::cout << List::listVector.size() << '\n'; // Prints 1
}
};
Foo fooObj;
//std::vector<int> List::listVector;
int main()
{
std::cout << List::listVector.size() << '\n'; // Prints 0
List::listVector.push_back(2);
std::cout << List::listVector.size() << '\n'; // Prints 1
}
它应该有用。我不是全局变量(我不使用它们)但我认为struct param不会使它成为真正的全局变量的问题。也许其他用户可以解释一下......
编辑:您还可以删除命名空间,我这样做就可以让List ::
Edit2:如果你想使用struct而不是
struct List
{
std::vector<int> listVector;
};
static List GlobL;
而不是使用GlobL.listVector,而不是struct obj ist static而不是struct的参数。
答案 2 :(得分:-3)
您必须了解您的程序不会从上到下运行。每个程序都将从main()函数开始。如果main()函数没有被调用,那么main()上面的所有代码基本上都会被忽略。
不应该在这里问这些问题。看起来你是一个初学者,你应该在提问之前先阅读自己的主题。