提问人:fisherwebdev 提问时间:9/29/2023 最后编辑:fisherwebdev 更新时间:9/29/2023 访问量:84
保护 std::array 中的单个值,同时允许完全覆盖
Protect individual values in std::array while allowing complete overwrite
问:
我有一个全局状态的数组。这是在嵌入式/微控制器环境中运行的,而不是我可能更关心全局状态的大型应用程序。
如何声明数组,使其成员无法更改,但仍可更新副本,并在需要时仍完全覆盖全局数组?
我有兴趣使用一个不可变数组,以便能够快速检查它在从突变函数返回时是否发生了变化。也就是说,如果内存地址发生了变化,那么我知道它已被复制和更新。
如果它已更新,那么我想用更新的版本覆盖原始全局数组。
但是,我想保护数组的各个值不会在 main() 中被意外覆盖,或者以其他方式访问和直接更新全局数组。也许我是偏执狂,但为了这个问题,让我们说这是一个合理的担忧。
唯一可能的更新应该通过复制/地址更新来完成。
此版本有效,但可以访问和直接更新全局数组:
#include <array>
#include <iostream>
std::array<int, 3> arr = {1, 2, 3}; // global array
std::array<int, 3> const * mutate(std::array<int, 3> const * ptr) {
// (*ptr)[2] = 9; // I like how this is prevented by const
// return ptr; // uncomment to test no mutation
// mutation via copy, retain new array on the heap
std::array<int, 3> * ret = new std::array<int, 3>;
std::copy((*ptr).begin(), (*ptr).end(), (*ret).begin());
(*ret)[0] = 9;
return ret;
}
int main() {
std::array<int, 3> const * retPtr = mutate(&arr);
if (retPtr == &arr) {
std::cout << "pointers are the same\n";
} else {
std::cout << "pointers are different\n";
arr = (*retPtr);
// do expensive things here with the new state
}
delete[] retPtr;
for (int val : arr) {
std::cout << val;
std::cout << "\n";
}
return 0;
}
首先,我尝试将数组声明为 .这使我无法完全覆盖数组。std::array<int, 3> const
std::array<int, 3> const arr = {1, 2, 3};
...
arr = (*retPtr); // Compilation error: no viable overloaded '='
然后我尝试将其声明为 ,但这阻止了我无法在突变函数中更改副本。std::array<int const, 3>
std::array<int const, 3> arr = {1, 2, 3};
std::array<int const, 3> * mutate(std::array<int const, 3> * ptr) {
std::array<int const, 3> * ret = new std::array<int const, 3> {0,0,0};
std::copy((*ptr).begin(), (*ptr).end(), (*ret).begin());
// Compilation error: cannot assign to return value because function 'operator[]'
// returns a const value
(*ret)[0] = 9;
return ret;
}
提前感谢您提供的任何帮助!
答:
2赞
doug
9/29/2023
#1
假设您使用的是 c++20 或更高版本,这现在是可行的。基本生活的改变使得更换对象成为可能,只要被替换的对象可以透明地替换。这限制了您不能更改数组的长度或其元素类型,因为这些会更改对象类型。请注意,由于只能由初始值设定项列表初始化,因此您必须列出此类列表中的每个元素,因此这对于大型数组来说会变得笨拙。std::array
#include <iostream>
#include <array>
#include <memory>
std::array< const int, 3> a{ 1,2,3 };
void mutate()
{
std::destroy_at(&a); // call destructor. not needed unless array elements have destructors
std::construct_at(&a, std::array<const int, 3> {2, 3, 4});
}
int main()
{
mutate();
std::cout << a[0] << '\n';
}
评论
0赞
fisherwebdev
10/2/2023
谢谢!虽然我可能会重新思考我是如何按照@paddy建议的思路来解决这个问题的,但我非常感谢这个对我所问的实际问题的回答。✌️
1赞
doug
10/2/2023
@fisherwebdev我也非常同意@paddy的评论,但想具体解决你的问题,因为这些技术并不为人所知,而且可能很有用std::array
上一个:如何防止类实例被更改
下一个:C# 对象返回的内部组件
评论
new
delete[]
*
const char* x
const char *x
const char * x