如何在没有动态内存分配(堆)的情况下为可变大小数组(向量)定义安全容器或视图? 约束:在目标平台上,我既不能使用动态内存分配,也不能使用C++标准库或任何其他第三方库。该语言仅限于C++11,不使用特定于编译器的扩展

如何在没有动态内存分配(堆)的情况下为可变大小数组(向量)定义安全容器或视图? 约束:在目标平台上,我既不能使用动态内存分配,也不能使用C++标准库或任何其他第三方库。该语言仅限于C++11,不使用特定于编译器的扩展,c++,arrays,C++,Arrays,在没有动态内存分配和有效内存保证的情况下,如何处理具有可变大小的数组或非所有者视图?大小不能是类型的一部分,例如std::array。数组可以静态定义。容器类型不需要拥有元素,但可以使用指向静态内存的指针进行初始化。主要目标是提供的数据/元素在有效内存中。其次是容器对象提供有效元素的数量 例如,应实现以下目标: 结构S{X;}; 其中S具有固定的大小,X是指向或由多个元素组成的某种容器。元素的数量不应是X型的一部分,也不应是类别模板,具体取决于尺寸,但对于每个对象来说是恒定的,并且可以是常量成员

在没有动态内存分配和有效内存保证的情况下,如何处理具有可变大小的数组或非所有者视图?大小不能是类型的一部分,例如std::array。数组可以静态定义。容器类型不需要拥有元素,但可以使用指向静态内存的指针进行初始化。主要目标是提供的数据/元素在有效内存中。其次是容器对象提供有效元素的数量

例如,应实现以下目标:

结构S{X;}; 其中S具有固定的大小,X是指向或由多个元素组成的某种容器。元素的数量不应是X型的一部分,也不应是类别模板,具体取决于尺寸,但对于每个对象来说是恒定的,并且可以是常量成员

必须确保指向的内存有效。例如,它不应指向以前的自动变量

以下事情没有解决:

使用std::vector或类似工具:需要在不使用动态内存分配的情况下实现该容器。 在一个类似的问题中使用。需要注意的是,如果我理解正确的话,必须静态地为每个对象提供最大容量。这是不可行的,因为无法估计什么是合适的限制。此外,还必须避免分配多余的静态内存,因为目标平台上的内存非常昂贵。 std::array不能为d,因为它的类型中包含大小。 . 我确实在一系列连续的对象上定义了一个非所有者视图,并用一个。以下是一个简化的示例:

这是示例类型:

样板 结构容器 { 公众: //包含大小的类型可用于将大小作为模板参数传递给“Container” 模板结构配置{}; //构造函数只接受指向具有静态存储持续时间的对象的指针 样板 Containerconst配置&:dataPOINTER,numberOfElementsN{} //!@返回元素数 constexpr std::size\t size const noexcept{return numberOfElements;} constexpr ElementType&运算符[]const std::size_t index const noexcept{返回数据[index];} 私人: ElementType*常量数据; 常数std::元素的大小和数量; }; 对指针静态存储持续时间的限制由构造函数实现。这需要一个Container::Configuration的对象。这反过来又需要一个指针作为模板参数,该参数必须按语言定义具有静态存储持续时间

以下是如何使用它:

//打印容器的元素 样板 无效打印元素约束容器和容器 { forstd::size\u t i=0;i 使用std::vector或类似工具:需要在不使用动态内存分配的情况下实现该容器

是的。因此,您可以编写自己的分配器,在静态池上工作。实际上,在静态分配的缓冲区上实现动态分配。我认为您应该这样做

从理论上讲,我从来没有能够正确地做到这一点。在某些环境中,您可以估计程序在编译时的最大堆栈使用量。没有递归函数,没有线程,所有库都是静态链接的/裸机目标,等等……剩下的内存可以使用静态分配的缓冲区进行动态分配。但是如果你无法计算它,你可以估计你系统上可用内存的最大值。好吧,如果你平台上的内存很宝贵,而你的内存又用完了,那么没有什么魔术可以帮你。除了用更少的内存重新编写所有内容,或者移动到内存更多的目标

。而一些标准容器(如std::vector)将分配器作为模板参数。假设您没有动态分配,您可以链接到自己实现的新函数和此类函数,这些函数可以自己实现标准分配器

无法使用std::array,因为它在其类型中包含大小

因此,使用std::array并将其转换为span

或者更好——编写自己的std::数组,它只接受一个大小为构造函数的静态缓冲区。或者正确——它是一个跨度

还有一个与C++11兼容的C++20跨实现,我建议使用它

template<typename T>
void printElements(T container)
{
    for (auto& i : container)
    {
        std::cout << container[i] << " ";
    }
    std::cout << std::endl;
}

// array with static storage duration 
int globalArray[] = { 1111, 2222, 3333, 4444 };

#include <tcb/span.hpp>
using tcb::span;

int main()
{    
    span<int> cB(globalArray, 
                 globalArray + sizeof(globalArray)/sizeof(globalArray[0]));
    printElements(cB);
    return 0;
}
它只是用来保存简单的类型,所以没有使用新的布局。对于任何更复杂的事情,这只是一个开始-你需要调用placement_new和ex上元素T的适当构造函数。push_back和调用析构函数来执行pop_back和类似的操作。我使用noexc ept在某些地方-代码库没有使用任何异常,因为它们通常调用动态分配

用法示例:

#include <iostream>

int main() {
    std::array<int, 5> _mem_for_vector;
    stack::vector<int> v{_mem_for_vector.data(), 5};
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);

    // will print 1 2 3 on separate lines
    for (auto& i : v) {
        std::cout << i << std::endl;
    }
}

你要的东西在集装箱箱里是做不到的。你要么需要分配足够大的静态内存块并使用它,要么使用动态分配并分配你需要的。如果你在编译时不知道数组大小的上限是什么,那么你要么在运行时分配内存,要么退出请求的大小过大。平台有什么操作系统?你使用什么编译器?@krisz:SCIOPTA RTOS和ARM clang 6。如果alloca合适的话,试试看。不安全内存的问题不就是吗?在这个方案中,vector的自动存储持续时间仍然存在吗?我正在搜索的机制应该排除指向此类缓冲区的指针。从其他的评论中,我得到的印象是,用C++11可能不可能满足这个要求?
#include <iostream>

int main() {
    std::array<int, 5> _mem_for_vector;
    stack::vector<int> v{_mem_for_vector.data(), 5};
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);

    // will print 1 2 3 on separate lines
    for (auto& i : v) {
        std::cout << i << std::endl;
    }
}