C++ 从 vector 获取结构,带有 & returns 指向未初始化结构的指针
C++ getting struct from vector with & returns pointer to non-initialized struct
函数 structFromVector()
returns 来自结构向量的结构。如果你编译下面的代码,那么 foo1Ptr->a
是一个空向量,而 foo2Ptr->a
是一个唯一元素为 1 的向量。为什么第一种情况下结构没有初始化?
如果 a
是一个整数而不是向量,并且您使用 a = 1;
而不是 a.push_back(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;
}
您正试图在此处使用临时 Foo
对象初始化指针:
Foo * foo1Ptr = &structFromVector();
您的编译器应该拒绝此代码(获取临时地址。)
如果要编译,在这一行之后,可以想象foo1Ptr
会指向一个不存在的对象(它会是一个悬空指针) .取消引用它会调用未定义的行为。尽管如此,讨论不符合规范的实现会做什么是相当推测性的。
因此,不要将指针绑定到临时对象,即使您的编译器允许您这样做。
一个解决方案(可能是您打算做的)是 return 对矢量元素的引用:
Foo& structFromVector() {
return fooList[0];
}
只要您不对向量执行使其无效的操作(例如,增加其大小以便重新分配),此引用就有效。)
因为您的代码中有未定义的行为。
这里:
Foo * foo1Ptr = &structFromVector();
structFromVector
returns 一个临时对象,foo1Ptr
成为指向这个临时对象的指针。在 ;
之后,这个临时对象被销毁,指针被称为 dangling(换句话说 - 它变得无效)。
第二种情况,
Foo foo2 = structFromVector();
Foo * foo2Ptr = &foo2;
foo2
现在是此临时对象的 copy,并且 foo2Ptr
指向此副本。所以,指针是有效的(而 foo1Ptr
是无效的)。 copy 将 alive 直到范围结束 - 在这种情况下,直到 main
的 }
。
它 "works" 与 int
的原因再次是 UB(未定义行为)——任何事情都可能发生。
EDIT 好吧,它似乎是格式错误的代码,因为编译器确实应该拒绝该代码。但因为它没有,所以它仍然是 UB。
函数 structFromVector()
returns 来自结构向量的结构。如果你编译下面的代码,那么 foo1Ptr->a
是一个空向量,而 foo2Ptr->a
是一个唯一元素为 1 的向量。为什么第一种情况下结构没有初始化?
如果 a
是一个整数而不是向量,并且您使用 a = 1;
而不是 a.push_back(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;
}
您正试图在此处使用临时 Foo
对象初始化指针:
Foo * foo1Ptr = &structFromVector();
您的编译器应该拒绝此代码(获取临时地址。)
如果要编译,在这一行之后,可以想象foo1Ptr
会指向一个不存在的对象(它会是一个悬空指针) .取消引用它会调用未定义的行为。尽管如此,讨论不符合规范的实现会做什么是相当推测性的。
因此,不要将指针绑定到临时对象,即使您的编译器允许您这样做。
一个解决方案(可能是您打算做的)是 return 对矢量元素的引用:
Foo& structFromVector() {
return fooList[0];
}
只要您不对向量执行使其无效的操作(例如,增加其大小以便重新分配),此引用就有效。)
因为您的代码中有未定义的行为。
这里:
Foo * foo1Ptr = &structFromVector();
structFromVector
returns 一个临时对象,foo1Ptr
成为指向这个临时对象的指针。在 ;
之后,这个临时对象被销毁,指针被称为 dangling(换句话说 - 它变得无效)。
第二种情况,
Foo foo2 = structFromVector();
Foo * foo2Ptr = &foo2;
foo2
现在是此临时对象的 copy,并且 foo2Ptr
指向此副本。所以,指针是有效的(而 foo1Ptr
是无效的)。 copy 将 alive 直到范围结束 - 在这种情况下,直到 main
的 }
。
它 "works" 与 int
的原因再次是 UB(未定义行为)——任何事情都可能发生。
EDIT 好吧,它似乎是格式错误的代码,因为编译器确实应该拒绝该代码。但因为它没有,所以它仍然是 UB。