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->afoo2Ptr->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 是无效的)。 copyalive 直到范围结束 - 在这种情况下,直到 main}

它 "works" 与 int 的原因再次是 UB(未定义行为)——任何事情都可能发生。


EDIT 好吧,它似乎是格式错误的代码,因为编译器确实应该拒绝该代码。但因为它没有,所以它仍然是 UB。