类内的 std::string 被破坏

3
我正在尝试构建一个简单的节点图库,以便为我心中的一些项目做准备。但是,在早期阶段我遇到了一个希望非常简单的路障,但它让我感到困惑。
我定义了称为NodeDefinitions的对象,它们是预定义配置(端口/参数数量等)中可以创建节点的配方。NodeDefinition对象包含PortDefinition对象,这些对象定义了每个输入/输出端口。这些PortDefinition对象包含它们的名称(除了本文为了简洁而删除的一些其他信息)。
我的Node类有一个Node()构造函数,它根据NodeDefition对象创建一个Node。当我使用它时,我创建包含指向相应PortDefinition的指针的Port对象。当我尝试打印端口的名称(从/存储在PortDefinition对象中派生)时,它会被破坏。
通过一些试错,我成功地发现如果我直接将std::vector传递给另一个Node()构造函数,那么一切似乎都正常工作。
在下面的示例代码中,我打印出端口名称(仅有一个端口),分别在构造函数内和调用者后。
定义类如下:
class PortDefinition
{
public:
    PortDefinition(const std::string & name) : m_name(name)
    {}
    std::string m_name;
};

class NodeDefinition
{
public:    
    NodeDefinition(std::vector<PortDefinition> portDefinitions) :
        m_portDefinitions(portDefinitions) 
    {}
    std::vector<PortDefinition> m_portDefinitions;
};

具体的对象类。
class Port
{
public:
    Port(PortDefinition * portDefinition) :
        m_portDefinition(portDefinition)
    {}
    const PortDefinition * m_portDefinition;
};

class Node
{
public:
    Node(NodeDefinition nodeDefinition) {
        std::vector<PortDefinition> portDefs = nodeDefinition.m_portDefinitions;
        for (auto & it : portDefs) {
            Port newPort = Port( &it );
            m_ports.push_back( newPort );
        }
        print();
    }

    Node(std::vector<PortDefinition> portDefs) {
        for (auto & it : portDefs) {
            Port newPort = Port( &it );
            m_ports.push_back( newPort );
        }
        print();
    }

    void print() const {
        std::cout << m_ports.size() << " : ";
        for (auto it : m_ports) {
            std::cout << "'" << it.m_portDefinition->m_name << "'" << std::endl; 
        }
    }
private:
    std::vector<Port> m_ports;
};

测试代码。
int main (int argc, const char *argv[])
{    
    std::vector<PortDefinition> portDefinitions;
    portDefinitions.push_back( PortDefinition("Port_A") );
    NodeDefinition nodeDefinition = NodeDefinition(portDefinitions);

    std::cout << "constuctor N1 : ";
    Node N1 = Node(nodeDefinition);
    std::cout << "main func N1  : ";
    N1.print();

    std::cout << std::endl;

    std::cout << "constuctor N2 : ";
    Node N2 = Node(portDefinitions);
    std::cout << "main func N2  : ";
    N2.print();
    return 1;
}

所有代码可以一起编译成一个文件。

当我运行它时,会得到以下输出。

constuctor N1 : 1 : 'Port_A'
main func N1  : 1 : ''

constuctor N2 : 1 : 'Port_A'
main func N2  : 1 : 'Port_A'

当我使用使用NodeDefinition对象的Node()构造函数后,打印出端口名称为空,有时我会得到垃圾值,这让我想到某些东西在以某种方式破坏内存,但我不太确定为什么会这样。

1个回答

4
std::vector<PortDefinition> portDefs = nodeDefinition.m_portDefinitions;
for (auto & it : portDefs) {
    Port newPort = Port( &it );
    m_ports.push_back( newPort );
}

问题出在这段代码上。portDefsnodeDefinition.m_portDefinitions的拷贝,在构造函数结束时被销毁。但你使用Port(&it)存储了对这些对象的指针。

构造函数中的print()应该可以正常工作,但是主函数中的print()现在访问已经销毁的拷贝,这是未定义的行为。

一个可能的解决方案是使用shared_ptr来存储您的PortDefinition或仅在Port中存储一个副本。


当然可以,非常感谢。使用shared_ptr就像魔法一样顺利运行。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接