【问题标题】:C++ vector objects going out of scopeC++ 向量对象超出范围
【发布时间】:2017-03-07 16:24:49
【问题描述】:

我无法理解如何正确构建指针向量(我对 C++ 很陌生)。我认为下面的代码总结了这个问题:

Mok.h

class Mok
{
public:
    Mok(int n) : m_num{n}
    int getNum() {return m_num}
private:
    int m_num;
};

Bar.h

class Bar
{
public:
    Bar();

    void setTiles();
    void printTiles();

private:
    std::vector<Mok*> m_tileSet;
};

Bar.cpp

void Bar::setTiles()
{
    for (int i = 0; i < 4; ++i)
    {
        m_tileSet.push_back(&Mok(i));
    }
}

void Bar::printTiles()
{
    for (const auto &mok : m_tileSet)
    {
        std::cout << mok->getNum() << " ";
    }
}

这个想法是打印存储在向量中的数字,但我得到了疯狂的数字(我知道这对整数没有多大意义,真正的代码更复杂,这是一种简化。想象 Mok 为一个大对象,以及包含数千个对象的向量)。在 setTiles() 内部,一切似乎都可以正常存储(VS 调试器是这样说的),但是当我到达 printTiles() 时,信息丢失了,我得到了像 -858993460.

我猜 Mok 对象超出了范围,所以引用(编辑:我的意思是地址)开始无处指向?这样做的方法是什么?

谢谢! :)

【问题讨论】:

  • m_tileSet.push_back(&amp;Mok(i)); should not even compile.
  • Mok(i) 在堆栈上分配一个 Mok 的实例,然后你存储它的地址。一旦超出范围,它就会被释放。你可以试试m_tileSet.push_back(new Mok(i));,让它在堆上分配。
  • 不需要指针。把它变成一个简单的std::vector&lt;Mok&gt;,然后收工。
  • 什么参考资料?您的代码没有使用它们。
  • 如果您在实际代码中确实需要一个指针向量,看起来该向量负责拥有这些资源,因此std::vector&lt;std::unique_ptr&lt;T&gt;&gt; 可能是合适的。不过,如果可能的话,一个简单的std::vector&lt;T&gt; 会更直接。

标签: c++ class object vector scope


【解决方案1】:

正如 Sam 和 Chris 在 cmets 中所建议的,一种方法是避免使用指针。以下代码有效:

Mok.h

class Mok
{
public:
    Mok(int n) : m_num{n}
    int getNum() {return m_num}
private:
    int m_num;
};

Bar.h

class Bar
{
public:
    Bar();

    void setTiles();
    void printTiles();

private:
    std::vector<Mok> m_tileSet;
};

Bar.cpp

void Bar::setTiles()
{
    for (int i = 0; i < 4; ++i)
    {
        m_tileSet.push_back(Mok(i));
    }
}

void Bar::printTiles()
{
    for (auto &mok : m_tileSet)
    {
        std::cout << mok.getNum() << " ";
    }
}

保留指针,使用 std::unique_ptr(感谢 cmets 中的 n.m.):

Bar.h

class Bar
{
public:
    Bar();

    void setTiles();
    void printTiles();

private:
    std::vector<std::unique_ptr<Mok>> m_tileSet;
};

Bar.cpp

void Bar::setTiles()
{
    for (int i = 0; i < 4; ++i)
    {

        m_tileSet.push_back(std::make_unique<Mok>(i)); // C++14
        //m_tileSet.push_back(std::unique_ptr<Mok>(new Mok(i))); // Previous to C++14
    }
}

void Bar::printTiles()
{
    for (auto &mok : m_tileSet)
    {
        std::cout << mok->getNum() << " ";
    }
}

【讨论】:

  • 你的编译器支持 c++14 吗?使用push_back(std::make_unique&lt;Mok&gt;(i)); 否则,push_back(std::unique_ptr&lt;Mok&gt;(new Mok(i)));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-23
  • 2015-01-15
相关资源
最近更新 更多