c++ Vector函数返回值不正确



我有class Amain()函数:

class A {
public: int num;
public: A* parent;
A(){};
A::A (const A &s)
{
this->num = s.num;
this->parent = s.parent;
}
public : vector <A> foo(A a)
{
A a1;
a1.num = a.num;
a1.parent = &a;

vector <A> list;
list.reserve(1);
list.push_back(a1);

A temp = list.front();

cout << temp.parent->num << endl;
return list;
}
}; 
int main()
{
A a; 
a.num =2;
vector <A> list = a.foo(a);
A temp = list.front();
cout << temp.parent->num << endl;
return 0;
}

问题是foo()中的cout按预期打印2,但main()中的cout打印了一个巨大的数字。

我认为问题是与内存重新分配有关的东西,因为我从多个来源读取,所以我尝试使用reserve(),但它不起作用。

谁能帮我解决这个问题?

foo()中,您通过值传递a参数。这意味着main()传递给foo()A对象将复制到a参数中。a参数本身是foo()的局部变量。因此,a1.parent被设置为指向一个局部变量。

然后list.push_back(a1);a1进行复制,复制parent指针。然后你做另一个复制当保存list.front()的结果到temp

因此,对foo()内部的temp.parent指针解引用是完全有效的,因为parent指向的a在内存中仍然有效。

然而,一旦foo()退出,a被销毁,留下复制的parent指针悬空,指向现在无效的内存。因此,在main()中,解引用parent指针是未定义行为,因为该指针不再指向原始a对象。

如果你为A对象的构造和销毁添加一些日志记录,你可以很容易地看到这一点,例如:

class A {
public:
int num = 0;
A* parent = nullptr;
 
A(){ cout << "A created: " << this << endl; }
 
A(const A &s) : num(s.num), parent(s.parent)
{
cout << "A copied: " << &s << " -> " << this << endl;
}
 
~A(){ cout << "A destroyed: " << this << endl; }
...
};

在线演示你会看到类似这样的记录:

A created: 0x7ffe5e735250                   // 'a' in main() is created
A copied: 0x7ffe5e735250 -> 0x7ffe5e735260  // 'a' in foo() is passed in by main()
A created: 0x7ffe5e7351e0                   // 'a1' in foo() is created
A copied: 0x7ffe5e7351e0 -> 0x5592f50b2e80  // 'a1' is copied into `list` in foo()
A copied: 0x5592f50b2e80 -> 0x7ffe5e7351f0  // list.front() is copied into 'temp' in foo()
(foo) temp.parent: 0x7ffe5e735260, num: 2   // parent is pointing at 'a' in foo()
// foo() exits, 'list' is transferred to main()
A destroyed: 0x7ffe5e7351f0                 // 'temp' in foo() is destroyed
A destroyed: 0x7ffe5e7351e0                 // 'a1' in foo() is destroyed
A destroyed: 0x7ffe5e735260                 // 'a' in foo() is destroyed !!!!!
A copied: 0x5592f50b2e80 -> 0x7ffe5e735260  // main() reuses freed memory for 'temp' in main() !!!!!
(main) temp.parent: 0x7ffe5e735260, num: 2  // parent is pointing at the wrong A object !!!!!
// main exits
A destroyed: 0x7ffe5e735260                 // 'temp' in main() is destroyed
A destroyed: 0x5592f50b2e80                 // `list` in main() is destroyed
A destroyed: 0x7ffe5e735250                 // 'a' in main() is destroyed

为了解决这个问题,将foo()改为通过引用来接受A对象(同时也将两个temp变量更改为A&引用):

vector<A> foo(A &a)

这样,在main()中,只要传递给foo()的本地a对象仍然有效,返回的parent指针将保持有效。

在线演示现在,您将看到类似这样的内容被记录:

A created: 0x7ffd7319e8b0                   // 'a' in main() is created
// 'a' in foo() is passed in by main()
A created: 0x7ffd7319e850                   // 'a1' in `foo() is created
A copied: 0x7ffd7319e850 -> 0x556ccff0fe80  // 'a1' is copied into 'list' in foo()
(foo) temp.parent: 0x7ffd7319e8b0, num: 2   // parent is pointing at 'a' in main()
// foo() exits, 'list' is transferred to main()
A destroyed: 0x7ffd7319e850                 // 'a1' in foo() is destroyed
(main) temp.parent: 0x7ffd7319e8b0, num: 2  // parent is still pointing at 'a' in main()
// main() exits
A destroyed: 0x556ccff0fe80                 // 'list' in main() is destroyed. 
A destroyed: 0x7ffd7319e8b0                 // 'a' in main() is destroyed !!!!!

相关内容

  • 没有找到相关文章

最新更新