函数structFromVector()
从结构向量返回结构。如果您编译下面的代码,那么foo1Ptr->a
是一个空向量,但foo2Ptr->a
是一个向量,其唯一元素是1.为什么在第一种情况下没有初始化结构?
如果a
是int而不是向量而不是a.push_back(1);
,则使用a = 1;
,foo1Ptr->a
和foo2Ptr->a
都等于1。为什么它在这种情况下有效而不是在第一种情况下呢?
struct Foo {
std::vector<int> a;
Foo() {
a.push_back(1);
}
};
std::vector<Foo> fooList;
Foo structFromVector() {
return fooList[0];
}
int main() {
fooList.push_back(Foo());
Foo * foo1Ptr = &structFromVector();
Foo foo2 = structFromVector();
Foo * foo2Ptr = &foo2;
}
答案 0 :(得分:3)
您正在尝试使用临时Foo
对象初始化指针:
Foo * foo1Ptr = &structFromVector();
您的编译器应该拒绝此代码(使用临时地址。)
如果要编译,在此行之后,可以想象foo1Ptr
将指向不存在的对象(它将是悬空指针)。取消引用它会调用未定义的行为。不过,讨论一个不合规的实现会做什么是非常具有推测性的。
因此,不要将指针绑定到临时,即使你的编译器允许你这样做。
一个解决方案,可能是您打算做的,是返回对向量元素的引用:
Foo& structFromVector() {
return fooList[0];
}
只要您不对使其无效的向量执行操作(例如,增加其大小以使其重新分配),此引用就有效。
答案 1 :(得分:1)
因为代码中有未定义的行为。
下面:
Foo * foo1Ptr = &structFromVector();
structFromVector
返回一个临时对象,foo1Ptr
成为指向此临时对象的指针。在;
之后,这个临时对象被销毁,指针被称为悬空(换句话说 - 它变得无效)。
在第二种情况下,
Foo foo2 = structFromVector();
Foo * foo2Ptr = &foo2;
foo2
现在是此临时对象的副本,foo2Ptr
指向此副本。因此,指针有效(foo1Ptr
无效)。 副本将 alive 直到范围结束 - 在这种情况下,直到main
的{{1}}。
它与}
“合作”的原因同样是UB(未定义行为) - 任何事情都可能发生。
编辑好吧,它似乎是格式错误的代码,因为编译器确实应该拒绝该代码。但事实并非如此,它仍然是UB。