繁体   English   中英

尝试从 std::array compile.data() 作为 c++20 中的 constexpr function 时出错

[英]error while trying to compile .data() from std::array as a constexpr function in c++20

我试图在编译时计算一个数组以加快某些函数的速度,但我遇到了一个错误,我无法在 cppreference 的帮助下解决该错误。

代码归结为:

#include <cstddef>
#include <array>

template<typename T, size_t size>
constexpr auto giveArray()
{
    std::array<T, size> arr;
    for(size_t i = 0; i < size; ++i)
        arr[i] = 0;
    return arr;
}

constexpr auto arr = giveArray<int,10>().data();

在编译时:“$ g++ -std=c++20 code.cpp” on ubuntu 我收到错误 that.data() is not a constexpr function 虽然它确实是。 为什么我会收到此错误以及如何修复它,同时仍在编译时运行此 function 并仅存储一个指针,而不是 std::array object?

只存储一个指针,而不是 std::array object?

你不能。

C++ 的规则不会因为您的代码在编译时执行而暂停(实际上,暂停这些规则是constexpr代码的一半)。 该数组需要存在才能使指向它的指针有意义。 这意味着当有人使用该指针时,数组 object 需要继续存在。

获取指向被销毁的临时对象的指针将使该指针指向被销毁的 object。这在编译时代码和运行时代码中都是一样的。 使用该指针在编译时和在运行时一样不起作用。 事实上,它的功能较少,因为必须在编译时诊断 UB(这是访问该指针将引发的)并将其转化为编译错误。

你可以试试

constexpr auto a0 = giveArray<int,10>();
constexpr auto arr = a0.data();

我的意思是...

constexpr auto arr = giveArray<int,10>().data();

您尝试使用指向 memory 的指针初始化arr ,该指针之后立即释放。

您可以解决修复从giveArray()收到的std::array

constexpr auto a0 = giveArray<int,10>();

所以arr收到一个指向 memory 的指针,它在初始化后保持稳定

constexpr auto arr = a0.data();

要初始化constexpr变量,您需要一个作为常量表达式的初始化器。 但是giveArray<int,10>().data(); 不是常量表达式。

这里开始

常量表达式是指作为常量表达式(定义如下)的允许结果的实体的左值核心常量表达式,或者是其值满足以下约束的纯右值核心常量表达式:

  • 如果该值是 class 类型的 object,则引用类型的每个非静态数据成员都引用一个实体,该实体是常量表达式的允许结果,
  • 如果该值是指针类型,则它包含具有 static 存储持续时间的 object 的地址,这样的 object ([expr.add]) 末尾的地址,非立即数 function 的地址,或 null 指针价值,
  • 如果该值是指向成员函数的指针类型,则它不会指定立即数 function,并且
  • 如果该值是 class 的 object 或数组类型,则每个子对象都满足该值的这些约束。 如果一个实体是一个 object 和 static 的存储持续时间,它不是一个临时的 object 或者是一个临时的 882829995402888 其值满足上述约束,或者如果它是一个非立即的 function,则该实体是常量表达式的允许结果。

表达式giveArray<int,10>().data(); 具有 prvalue 的值类别,因此它不是 glvalue 表达式。 这意味着它必须是“其值满足以下约束的纯右值核心常量表达式”才能成为常量表达式。 由于表达式的计算结果为指针类型,因此它必须满足以下条件:

  • 如果该值是指针类型,则它包含具有 static 存储持续时间的 object 的地址,这样的 object ([expr.add]) 末尾的地址,非立即数 function 的地址,或 null 指针价值

在这种情况下,它不是那些东西,所以它不是常量表达式。 但是,如果您将代码更改为:

const auto my_array = giveArray<int,10>();
constexpr auto arr = my_array.data();

my_array是一个全局变量,这意味着它有 static 个存储持续时间。 data()返回指向该存储的指针,这使其成为常量表达式。

简而言之,这条规则使你在编译时执行代码时不能有一个指针值无效的指针。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM