为什么从函数返回时向量内部的指针会发生变化?

Why are pointers inside of a vector changing when being returned from a function?

在我的实际应用中,我使用双向连接的边列表来存储平面的分段,但我试图减少代码来显示我的问题。

我有一个包含自定义结构的列表,我需要将其转换为指向列表中存储的对象的指针向量。当我这样做时,在发生转换的函数内部,我的向量中的指针与指向列表中对象的指针相同,但在函数外部(当我将 return 值存储在内部时一个变量)指针已经改变。为什么会这样?它与 moving/copying 值有关吗?怎么了?

感谢大家的帮助!

struct MyStruct
{
    MyStruct* my_other_struct;
}

static std::vector<MyStruct*> structPointers(
    std::list<MyStruct> structs)
{
    std::vector<MyStruct*> struct_pointers;
    struct_pointers.reserve(structs.size());
    std::transform(structs.begin(), structs.end(),
        std::back_inserter(struct_pointers),
        [](MyStruct& ms){ return &ms; });

    for (const MyStruct* ms : struct_pointers)
    {
        // this seems to print out the correct memory address
        std::cout << ms << std::endl;
    }

    return struct_pointers;
}

int main()
{
    std::list<MyStruct> structs;
    structs.push_back(Struct());
    structs.push_back(Struct());
    structs.front().my_other_struct = &structs.back()
    structs.back().my_other_struct = &structs.front()

    std::vector<MyStruct*> struct_pointers = structPointers(structs)

    // I get two different addresses printed out here and I don't understand why
    std::cout << &structs.front() << std::endl;
    std::cout << struct_pointers.front() << std::endl;

    // I get two different addresses printed out here and I don't understand why
    std::cout << &structs.back() << std::endl;
    std::cout << struct_pointers.back() << std::endl;

    return 0;
}

您需要通过引用接受 structs,否则您在函数内创建的指针指的是原始 MyStruct 对象的副本。

static std::vector<MyStruct*> structPointers(
    std::list<MyStruct>& structs) // <-- take by reference

这是一个demo

您是按值而不是按引用传递列表,因此您在调用函数时会获得列表的新副本,并且此副本会在 return 从函数中销毁。发生的事情是您复制函数的列表,因此副本具有与原始元素不同的元素,然后将副本元素的地址附加到您 return 的向量,因此地址属于副本而不是原本的 。向量中的指针也将悬空(指向被破坏的对象)

解决方案:按引用传递而不是按值传递:

static std::vector<MyStruct*> structPointers(
    std::list<MyStruct>& structs)