diff --git a/src/op_cache.h b/src/op_cache.h
index e2f26008723f444dc516e2850c471078b08afb2e..fa87b9804ff6a0ea3fde68570101b1a53f695735 100644
--- a/src/op_cache.h
+++ b/src/op_cache.h
@@ -102,9 +102,14 @@ public:
                 //std::cout << "onValuesAdded: " << viop.first->second.refCount << " refs for value " << v->id << std::endl;
             }
         }
-        auto list = listeners;
-        for (auto& l : list)
-            l.second.get_cb(l.second.filter.filter(newValues), false);
+        if (not listeners.empty()) {
+            std::vector<LocalListener> list;
+            list.reserve(listeners.size());
+            for (const auto& l : listeners)
+                list.emplace_back(l.second);
+            for (auto& l : list)
+                l.get_cb(l.filter.filter(newValues), false);
+        }
     }
     void onValuesExpired(const std::vector<Sp<Value>>& vals) {
         std::vector<Sp<Value>> expiredValues;
@@ -117,9 +122,14 @@ public:
                     values.erase(vit);
             }
         }
-        auto list = listeners;
-        for (auto& l : list)
-            l.second.get_cb(l.second.filter.filter(expiredValues), true);
+        if (not listeners.empty()) {
+            std::vector<LocalListener> list;
+            list.reserve(listeners.size());
+            for (const auto& l : listeners)
+                list.emplace_back(l.second);
+            for (auto& l : list)
+                l.get_cb(l.filter.filter(expiredValues), true);
+        }
     }
 
     void addListener(size_t token, ValueCallback cb, Sp<Query> q, Value::Filter filter) {
@@ -178,26 +188,26 @@ public:
         }
         if (op == ops.end()) {
             // New query
-            op = ops.emplace(q, OpCache{}).first;
-            auto& cache = op->second;
+            op = ops.emplace(q, std::unique_ptr<OpCache>(new OpCache)).first;
+            auto& cache = *op->second;
             cache.searchToken = onListen(q, [&](const std::vector<Sp<Value>>& values, bool expired){
                 return cache.onValue(values, expired);
             });
         }
         auto token = nextToken_++;
-        if (token == 0)
-            token++;
-        op->second.addListener(token, get_cb, q, filter);
+        if (nextToken_ == 0)
+            nextToken_++;
+        op->second->addListener(token, get_cb, q, filter);
         return token;
     }
 
     bool cancelListen(size_t gtoken, std::function<void(size_t)> onCancel) {
         for (auto it = ops.begin(); it != ops.end(); it++) {
-            if (it->second.removeListener(gtoken)) {
-                if (it->second.isDone()) {
-                    auto ltoken = it->second.searchToken;
+            if (it->second->removeListener(gtoken)) {
+                if (it->second->isDone()) {
+                    auto cache = std::move(it->second);
                     ops.erase(it);
-                    onCancel(ltoken);
+                    onCancel(cache->searchToken);
                 }
                 return true;
             }
@@ -207,10 +217,10 @@ public:
 
     std::vector<Sp<Value>> get(Value::Filter& filter) const {
         if (ops.size() == 1)
-            return ops.begin()->second.get(filter);
+            return ops.begin()->second->get(filter);
         std::map<Value::Id, Sp<Value>> c;
         for (const auto& op : ops) {
-            for (const auto& v : op.second.get(filter))
+            for (const auto& v : op.second->get(filter))
                 c.emplace(v->id, v);
         }
         std::vector<Sp<Value>> ret;
@@ -222,13 +232,13 @@ public:
 
     Sp<Value> get(Value::Id id) const {
         for (const auto& op : ops)
-            if (auto v = op.second.get(id))
+            if (auto v = op.second->get(id))
                 return v;
         return {};
     }
 
 private:
-    std::map<Sp<Query>, OpCache> ops;
+    std::map<Sp<Query>, std::unique_ptr<OpCache>> ops {};
     size_t nextToken_ {1};
 };