向量成员已重置且无法访问

时间:2018-07-30 15:48:32

标签: c++ pointers vector forward-declaration

我有两个项目,一个基本客户端和一个动态库。 这是客户端中发生的事情:

int main()
{
    Scrutinizer scru;
    scru.Scrutinize();
    return 0;
}

在DLL中,Scrutinizer类就是这样的(__ declspec(dllexport),为了清晰起见,省略了此类)

标题

class ProcessesGenerator;

    class Scrutinizer
    {
    public:
    Scrutinizer();
    ~Scrutinizer();
    ProcessesGenerator *ProcGenerator
    void Scrutinize();
};

ProcessesGenerator的前声明对我来说是“强制性”,以避免某种形式的循环引用。

.cpp文件中的构造函数

这是我的初始化方式:

Scrutinizer::Scrutinizer()
{
    ProcGenerator = &ProcessesGenerator();
}

有关此ProcessesGenerator类的更多信息:

标题

class ProcessesGenerator
{

public:
    ProcessesGenerator();
    ~ProcessesGenerator();
    WinFinder winFinder;
    std::vector<std::string> fooCollec;

    void GenerateProcesses();
};

ProcessesGenerator.cpp

构造函数:

ProcessesGenerator::ProcessesGenerator()
{
    //winFinder = WinFinder();//problem will be the same with or without this line
    fooCollec = std::vector<std::string>{"one", "two", "three"};
}

构造函数中的断点表明,向量已使用选定的值初始化。

问题功能:

void ProcessesGenerator::GenerateProcesses() {
    std::string foo = "bar";
    fooCollec = std::vector<std::string>{};//read access violation
    fooCollec.push_back(foo);//read access violation
    winFinder.SomeVector= std::vector<std::string>{};//read access violation
}

在那里,我可以看到vector的大小被重置为0。任何尝试重新初始化它或推入元素的操作都会导致读取访问冲突。与它的WinFinder的vecotr成员相同会员。我想这个缺陷很明显,但是我真的不明白,

谢谢!

2 个答案:

答案 0 :(得分:4)

您的问题在于

Scrutinizer::Scrutinizer()
{
    ProcGenerator = &ProcessesGenerator();
}

您正在做的是获取一个临时对象的地址。该对象将被销毁,并在该行的末尾,您将获得一个指向有效对象的指针。

解决此问题的旧方法是使用

Scrutinizer::Scrutinizer()
{
    ProcGenerator = new ProcessesGenerator();
}

但是现在您必须实现复制构造函数,复制赋值运算符和析构函数。由于您使用的是现代编译器,因此您可以将ProcGenerator设为std:unique_ptr<ProcessesGenerator>,然后使Scrutinizer()变成

Scrutinizer::Scrutinizer() : ProcGenerator(make_unique<ProcessesGenerator>()) {}

我还要补充一点,&ProcessesGenerator();甚至不应该编译。不幸的是,MSVS具有非标准扩展名,因此可以对其进行编译。您可以打开/Za编译器选项(强制ANSI兼容性),然后会出现类似错误

  

错误C2102:“&”需要左值

答案 1 :(得分:1)

ProcGenerator = &ProcessesGenerator();行构成一个临时ProcessesGenerator,获取其地址,然后将其放入您的ProcGenerator指针中。然后临时文件被销毁,留下垃圾。

您可能希望将其分配到堆ProcGenerator = new ProcessesGenerator;上,但是即使在那种情况下,我也强烈建议使用unique_ptr而不是原始指针。