juce - juce容器
JUCE 框架提供了一系列高效、易用的容器类,用于管理数据集合。这些容器在设计和性能上针对实时音频处理(低延迟、无锁)和跨平台兼容性进行了优化。以下是 JUCE 中常用的容器及其关键用法:
1. juce::Array<T>
-
用途:动态数组,类似
std::vector,但优化了内存分配策略(适合实时音频场景)。 -
特点:
-
连续内存存储,支持快速随机访问。
-
自动内存管理,支持动态扩展。
-
提供
add(),insert(),remove(),sort()等方法。
-
-
示例:
juce::Array<int> numbers; numbers.add(10); // 添加元素 numbers.add(20, 30); // 添加多个元素 numbers.remove(0); // 删除索引0的元素 numbers.sort(); // 排序(默认升序)
2. juce::OwnedArray<T>
-
用途:拥有对象所有权的动态数组,自动管理对象生命周期(类似
std::vector<std::unique_ptr<T>>)。 -
特点:
-
容器销毁时,自动删除所有元素。
-
适合管理动态分配的复杂对象(如 UI 组件、音频处理器)。
-
-
示例:
juce::OwnedArray<juce::Button> buttons; buttons.add(new juce::TextButton("Click Me")); // 添加对象 buttons.clear(); // 自动删除所有按钮对象
3. juce::ReferenceCountedArray<T>
-
用途:管理引用计数的对象集合(类似
std::vector<std::shared_ptr<T>>)。 -
特点:
-
元素必须继承自
juce::ReferenceCountedObject。 -
自动跟踪引用计数,无引用时自动释放对象。
-
-
示例:
class MyObject : public juce::ReferenceCountedObject { // ... }; juce::ReferenceCountedArray<MyObject> refArray; refArray.add(new MyObject()); // 添加引用计数对象
4. juce::HashMap<Key, Value>
-
用途:键值对哈希表,类似
std::unordered_map。 -
特点:
-
支持快速查找(O(1) 平均复杂度)。
-
键需实现
hashCode()和operator==。
-
-
示例:
juce::HashMap<juce::String, int> scores; scores.set("Alice", 100); // 插入键值对 int aliceScore = scores["Alice"]; // 获取值
5. juce::StringArray
-
用途:专门存储字符串的优化容器。
-
特点:
-
提供字符串专用的方法(如
joinIntoString(),contains())。 -
支持快速字符串匹配和操作。
-
-
示例:
juce::StringArray names; names.add("John"); names.add("Jane"); juce::String joined = names.joinIntoString(", "); // "John, Jane"
6. juce::LinkedListPointer<T>
-
用途:高效的单链表实现,适合频繁插入/删除的场景。
-
特点:
-
轻量级,无额外内存开销。
-
需手动管理节点(通常用于底层数据结构)。
-
-
示例:
struct Node { juce::LinkedListPointer<Node> next; int data; }; Node head; head.next.insertNext(new Node{ {}, 42 }); // 插入节点
7. juce::Variant
-
用途:存储任意类型的数据(类似
std::any)。 -
特点:
-
支持基本类型、字符串、自定义对象。
-
通过
get<T>()安全获取值。
-
-
示例:
juce::Variant value = 42; // 存储整数 int num = value.get<int>(); // 获取整数 value = juce::String("Hello"); // 存储字符串
8. juce::SparseSet
-
用途:存储不连续整数范围的集合(如选中的 MIDI 音符编号)。
-
特点:
-
高效存储稀疏数据。
-
支持范围操作(如
addRange(),contains())。
-
-
示例:
juce::SparseSet selectedNotes; selectedNotes.addRange({60, 72}); // 添加音符60到72 bool isSelected = selectedNotes.contains(64); // 检查是否包含
9. juce::AbstractFifo
-
用途:无锁环形缓冲区,用于多线程生产者-消费者模式(如音频线程和GUI线程通信)。
-
特点:
-
线程安全,适合实时音频处理。
-
需继承并实现
read()和write()方法。
-
-
示例:
class AudioBufferFifo : public juce::AbstractFifo { public: AudioBufferFifo(int size) : juce::AbstractFifo(size) {} void write(const float* data, int numSamples) { /* 实现写入逻辑 */ } void read(float* output, int numSamples) { /* 实现读取逻辑 */ } };
10. juce::ValueTree
-
用途:树形结构数据容器,支持序列化、撤销重做和监听(常用于插件状态管理)。
-
特点:
-
类似 XML 或 JSON 的结构化数据。
-
可附加监听器(
juce::ValueTree::Listener)监听数据变化。
-
-
示例:
juce::ValueTree state("PluginState"); state.setProperty("volume", 0.8, nullptr); // 设置属性 float volume = state["volume"]; // 获取属性
选择容器的最佳实践
-
实时音频线程:优先使用
juce::Array或juce::AbstractFifo(避免动态内存分配)。 -
对象所有权管理:使用
OwnedArray(自动释放)或ReferenceCountedArray(共享所有权)。 -
键值对存储:
HashMap或juce::NamedValueSet(简单键值对)。 -
跨线程通信:
AbstractFifo+ 无锁设计。 -
复杂数据模型:
ValueTree(支持序列化和监听)。
与 STL 容器的对比
| JUCE 容器 | 类似 STL 容器 | 主要差异 |
|---|---|---|
juce::Array |
std::vector |
内存预分配策略更激进,适合实时场景 |
juce::OwnedArray |
std::vector<std::unique_ptr> |
自动释放对象 |
juce::HashMap |
std::unordered_map |
接口更简洁,键需实现 hashCode() |
代码示例:遍历 juce::Array
juce::Array<int> values {1, 2, 3, 4, 5};
// 传统遍历
for (int i = 0; i < values.size(); ++i) {
DBG(values[i]);
}
// 范围遍历(C++11)
for (auto& value : values) {
DBG(value);
}
通过灵活选择容器,可以显著提升 JUCE 应用的性能和代码可维护性。

浙公网安备 33010602011771号