c++ 如何将std::array的指针作为const传递?

q0qdq0h2  于 2023-03-25  发布在  其他
关注(0)|答案(2)|浏览(154)

我想创建一个std::array指针,而不声明指针指向的类型为const,这样我就可以通过取消引用这些指针来更改数组指针指向的值。
所以我不想这么做:

#include <array>

int main()
{
    int a = 5;
    int b = 10;
    std::array<const int*, 2> arr = { &a, &b };     // with const
    *(arr[0]) = 20;                                 // Because this is not possible.
}

但是这个:

#include <array>

int main()
{
    int a = 5;
    int b = 10;
    std::array<int*, 2> arr = { &a, &b };           // without const
    *(arr[0]) = 20;                                 // Because now it is possible.
}

现在我想把这个数组传递给一个函数,这样这个函数就可以通过解引用这些指针来改变数组指针所指向的值:

#include <array>

void test(const std::array<int*, 2>& arr)
{
    *(arr[0]) = 20;     // I want this to not be possible (in this example it is)
}

int main()
{
    int a = 5;
    int b = 10;
    std::array<int*, 2> arr = { &a, &b };
    test(arr);
}

我如何才能做到这一点?因为它是可能的C数组:

void test(int const * const * const arr)
{
    *(arr[0]) = 20;     // this is not possible
}

int main()
{
    int a = 5;
    int b = 10;
    int* arr[2] = {&a, &b};
    test(arr);
}

我想这也可以用C++ std数组实现。
多谢帮忙。谢谢。

a8jjtwal

a8jjtwal1#

很不幸你的要求是不可能的。
这种情况下的根本问题是const只在顶层传播。
因此,使指针为const只会使指针本身为const,而不会使指向的对象为const。
这对于任何包含指针的类都是正确的,而不仅仅是std::arraygodbolt

std::array<int*, 2> arr = { &a, &b };
auto const& arrref = arr;
static_assert(std::same_as<decltype(arrref[0]), int* const&>); // not int const * const&!

struct Foo {
    int* ptr;
    auto& get() const { return ptr; }
};
Foo foo{&a};
auto const& fooref = foo;
static_assert(std::same_as<decltype(fooref.get()), int* const&>); // not int const * const&!

你需要一个指针类型来将它的常量传播给被指向的类型。
std::propagate_const(不幸的是,作为库基础TS的一部分,它仍然是实验性的)就是这样做的:它 Package 了一个类似指针的类型,以便将const传播到指向的对象。
示例:godbolt

using std::experimental::propagate_const;

void test(std::array<propagate_const<int*>, 2> const& arr)
{
    // ill-formed:
    //*arr[0] = 20;
}

int main()
{
    int a = 5;
    int b = 10;
    std::array<propagate_const<int*>, 2> arr = {&a, &b};
    test(arr);

    // well-formed
    *arr[0] = 42;

    return 0;
}

另一个适用于C++20的选项是使用std::span
std::span本质上只是一个指向数组的指针,因此您可以根据需要向元素类型添加尽可能多的const(就像在您的c-array示例中一样,您将数组衰减为指针以添加常量)
示例:godbolt

void test(std::span<int const* const> arr)
{
    // ill-formed:
    //*arr[0] = 20;
}

int main()
{
    int a = 5;
    int b = 10;
    std::array<int*, 2> arr = {&a, &b};
    test(arr);

    // well-formed
    *arr[0] = 42;

    return 0;
}
bd1hkmkf

bd1hkmkf2#

我不认为有一种方法可以达到你提到的特定要求。但是,传递解引用的整数是可以的,通过:

int modify(const int a)
{
    return a;
}

int main()
{
    int a = 5;
    int b = 10;
    std::array<int *, 2> arr = {&a, &b}; // with const
    modify(*(arr[0]));      // Because this is not possible.
}

我不能在函数中修改它的值。虽然你可以简单地使用一个函数来处理这个问题,但它并不是那么开箱即用。

function A {
    change array to const int array
    pass const array into the function
}

或者稍微修改数组类中的运算符函数。(矫枉过正)

相关问题