gpt4 book ai didi

c++ - 返回对 std::vector 元素的引用会导致崩溃

转载 作者:行者123 更新时间:2023-12-02 01:31:00 29 4
gpt4 key购买 nike

下面的示例不会崩溃,但使用 MSVC 编译器版本 19.32.31332 不打印任何内容,并使用 GCC 打印“def”:

#include <string>
#include <vector>
#include <set>
#include <ranges>
#include <iostream>

template <class R, class Value>
concept range_over = std::ranges::range<R> &&
std::same_as<std::ranges::range_value_t<R>, Value>;

const std::string& find1(const std::vector<std::string>& v)
{
return v[1];
}

template <range_over<std::string> Range>
std::reference_wrapper<std::string> find2(Range range)
{
return *(range.begin() + 1);
}

int main()
{
std::vector<std::string> v = { "abc", "def", "ghi" };

//find1 always prints "def"
//std::cout << find1(v);

std::cout << find2(v).get() << std::endl;

return 0;
}

但在我的实际应用程序中,MSVC 编译器版本 19.32.31332 中类似的代码会崩溃。

代码正确吗? func2(v) 调用后 v 有效吗?

最佳答案

find2按值获取范围。因此,您将返回对函数参数对象的引用,该对象是 vector v 的拷贝在main ,这本身很可能不是该函数的意图。例如。通过返回的引用进行的修改不会反射(reflect)在 v 中.


函数参数是否在函数返回时或在包含函数调用的完整表达式之后被销毁是由实现定义的。实际上,这将由所使用的 C++ ABI 决定(这也可能解释了 MSVC 和 GCC/Clang 之间的不同行为)。

因此,根据所使用的实现如何定义它,它可能有也可能没有未定义的行为。如果函数返回时参数对象被销毁,则调用operator<<将通过悬空引用读取值。否则它是一个有效的程序并将打印 def .


在 C++17 之前,标准规定函数参数对象总是在函数返回时被销毁。这已更改为 CWG issue 1880 。然而,正如问题所指出的,实际的实现/ABI 确实具有(当时)在完整表达式末尾销毁它们的不合格行为,并且选择了决议中的实现定义,以便这些 ABI 不会休息。因此,实际上,该标准只是根据实际情况进行了调整。

关于c++ - 返回对 std::vector 元素的引用会导致崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73297830/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com