能否在类初始化列表中定义数组大小?非静态无hack实现可行吗?
类中动态大小数组的常见问题解答
先直接给你明确结论:你没法在初始化列表里定义数组大小,而且你给出的示例代码里用非static成员作为数组大小的写法,在标准C++里是完全不合法的。原因很简单:普通数组的大小必须是编译阶段就能确定的常量表达式,而buf_size是每个对象实例化时才会被初始化的成员,编译器在编译的时候根本不知道它的值,自然没法确定数组的大小。
接下来针对你第二个问题——不把数组大小设为static的情况下,怎么合理实现类中动态大小的存储,给你几个完全合规、不需要任何hack的方案:
方案1:用std::vector<uint8_t>(最推荐)
这是C++里处理动态内存最常用也最省心的方式,vector会自动帮你管理内存分配和释放,还支持动态扩容(如果后续需要的话)。修改后的代码可以写成这样:
#include <vector> #include <cstdint> class Byte_Buffer { public: // 直接用传入的大小初始化vector Byte_Buffer(uint16_t bs) : storage(bs) {} private: std::vector<uint8_t> storage; // 如果需要单独存大小,也可以加个成员,vector本身也能通过size()获取 // const uint16_t buf_size{static_cast<uint16_t>(storage.size())}; };
要是你想保留buf_size成员,也很简单:
#include <vector> #include <cstdint> class Byte_Buffer { public: Byte_Buffer(uint16_t bs) : buf_size(bs), storage(bs) {} private: const uint16_t buf_size; std::vector<uint8_t> storage; };
方案2:用智能指针管理动态数组
如果你不想用vector,也可以用std::unique_ptr来托管动态分配的数组,这样不用手动写析构函数释放内存,同样很安全:
#include <memory> #include <cstdint> class Byte_Buffer { public: Byte_Buffer(uint16_t bs) : buf_size(bs), storage(std::make_unique<uint8_t[]>(bs)) {} private: const uint16_t buf_size; // unique_ptr会在对象销毁时自动释放数组内存 std::unique_ptr<uint8_t[]> storage; };
方案3:手动动态分配(不推荐)
当然你也可以自己用new和delete[]来实现,但这种方式需要严格遵循三法则(写析构函数、拷贝构造、拷贝赋值),很容易因为疏忽导致内存泄漏或者浅拷贝问题,所以除非有特殊需求,否则不建议这么做:
#include <cstdint> #include <algorithm> // 用于std::copy class Byte_Buffer { public: Byte_Buffer(uint16_t bs) : buf_size(bs), storage(new uint8_t[bs]) {} // 析构函数释放内存 ~Byte_Buffer() { delete[] storage; } // 拷贝构造函数:必须深拷贝,避免多个对象共享同一块内存 Byte_Buffer(const Byte_Buffer& other) : buf_size(other.buf_size), storage(new uint8_t[other.buf_size]) { std::copy(other.storage, other.storage + other.buf_size, storage); } // 拷贝赋值运算符:同样要深拷贝,还要处理自赋值情况 Byte_Buffer& operator=(const Byte_Buffer& other) { if (this != &other) { delete[] storage; buf_size = other.buf_size; storage = new uint8_t[buf_size]; std::copy(other.storage, other.storage + buf_size, storage); } return *this; } private: const uint16_t buf_size; uint8_t* storage; };
最后再啰嗦一句:有些编译器(比如GCC)支持变长数组(VLA)作为语言扩展,允许你写类似uint8_t storage[buf_size]的代码,但这不是标准C++的内容,属于编译器特定的hack,换个编译器(比如MSVC)就编译不过了,所以绝对不要依赖这种写法。
内容的提问来源于stack exchange,提问作者joe blogs
相关产品推荐
相关产品推荐

