【问题标题】:The address of a member object is changing immediately after constructor成员对象的地址在构造函数后立即更改
【发布时间】:2016-11-29 06:01:36
【问题描述】:

如果您想查看导致此问题的代码,可以在此处查看和克隆项目:https://github.com/NickChapman/RuM/tree/63047e457745558403ea807534e4f5b9930cfeb8

值得注意的是,在我的构造函数内部(RuMParser.cpp 第 20 行):

this->globalScope = Scope();
std::cout << &(this->globalScope) << std::endl;

然后在构造函数完成后立即获得(RuM.cpp 第 63 行):

std::cout << &(this->parser.globalScope) << std::endl;

这些的输出是:

0x7fff57ac5318
0x7fff57ac6988

为什么它们不一样?在剩下的所有时间里,地址将保持固定在第二个值。为什么离开构造函数后会改变?

我在第一次打印后立即尝试建立指针时注意到了这个问题。构造函数完成后,指针指向旧地址,我很困惑为什么。

我怀疑这与复制构造函数或类似的东西有关。

编辑:作为参考,如果您尝试构建源代码并运行,您可以:

cmake .
make

然后

./rum

输入x=1;$会导致程序段错误。

【问题讨论】:

    标签: c++ pointers memory-management constructor memory-address


    【解决方案1】:
    this->parser = RuMParser(tokenList);
    std::cout << &(this->parser.globalScope) << std::endl;
    

    首先,创建一个临时的RuMParser,这是您获得第一个打印件的时间。然后将临时复制构造为this-&gt;parser。这意味着,globalScope 再次默认构造。因此后面打印的地址不同。

    好吧,代码中有很多有问题的/非惯用的东西,但我只会坚持对这个问题很重要的东西。您可以将构造函数重写为:

    RuMInterpreter::RuMInterpreter(): 
          tokenList(std::make_shared<std::vector<Token>>())
         ,parser(tokenList) 
    {
    ....
    } 
    

    尽可能总是首选成员初始化器列表。我猜它也是有效 C++ 书籍中的项目之一。

    【讨论】:

    • 不使用指针有没有办法阻止复制构造函数的调用?
    • 首先按照您想要的方式构造对象,而不是在构造完成后分配它。您还可以将boost::optional 用作“shell”,以后可以将对象构造到其中。
    • @NickChapman 用你可能应该做的事情更新了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多