c++ 用 std::string 覆盖 [] 运算符
c++ overwrite [] operator with std::string
我基本上是在尝试为 std::map
创建一个线程安全的包装器 class。
由于我来自 C,我很难搞清楚 C++ 的所有细微差别。
我正在尝试覆盖 [] operator
以采用 std::string
参数将其传递给我的 std::map
成员。
根据 std::map::operator[]
的参考,这应该可以正常工作:
T& operator[]( const Key& key );
这是我的class:
thread_map.hpp
#ifndef THREAD_MAP_H
#define THREAD_MAP_H
#include <map>
#include <functional>
#include <mutex>
template <class T>class Thread_map
{
private:
std::map<std::string, T> map;
std::mutex map_mutex;
public:
~Thread_map();
T& at(size_t pos);
T& operator[](std::string &key);
size_t size() const;
bool empty() const;
void clear();
void insert(std::pair<std::string, T> pair);
T& erase(const std::string &key);
bool for_each(std::function<bool (Thread_map, std::string&, T&)> fun);
};
template<class T> Thread_map<T>::~Thread_map()
{
this->map.clear();
}
template<class T> T& Thread_map<T>::at(size_t pos)
{
T *value;
this->map_mutex.lock();
value = this->map.at(pos);
this->map_mutex.unlock();
return value;
}
template<class T> T& Thread_map<T>::operator[](std::string &key)
{
this->map_mutex.lock();
T &value = this->map[key];
this->map_mutex.unlock();
return value;
}
template<class T> size_t Thread_map<T>::size() const
{
size_t size;
this->map_mutex.lock();
size = this->map.size();
this->map_mutex.unlock();
return size;
}
template<class T> bool Thread_map<T>::empty() const
{
bool empty;
this->map_mutex.lock();
empty = this->map.empty();
this->map_mutex.unlock();
return empty;
}
template<class T> void Thread_map<T>::clear()
{
this->map_mutex.lock();
this->map.clear();
this->map_mutex.unlock();
}
template<class T> void Thread_map<T>::insert(std::pair<std::string, T> pair)
{
this->map_mutex.lock();
this->map.insert(pair);
this->map_mutex.unlock();
}
template<class T> T& Thread_map<T>::erase(const std::string &key)
{
T *value;
this->map_mutex.lock();
value = this->map.erase(key);
this->map_mutex.unlock();
return value;
}
template<class T> bool Thread_map<T>::for_each(std::function<bool
(Thread_map, std::string&, T&)> fun)
{
}
#endif
我将实现放入头文件中,因为我听说您使用模板 classes 来实现。我说得对吗?
我的问题是,当我尝试致电接线员时
Thread_map<std::string> map;
map["mkey"] = "value";
g++ 在 map["mkey"] 上抛出一个无效的初始化错误。
就我的理解而言,问题是 mkey
被编译为 std::string("mkey")
这只是值,而不是引用。
但是,为什么或如何执行以下操作?
std::map<std::string, std::string> map;
map["mkey"] = "value";
我的意思是我可以按值传递字符串,但这似乎效率不高。
引用需要一个可以修改的变量地址。对于左值字符串("some string"),没有可以修改值的地址。
我知道有一些方法可以解决这个问题:
删除引用(不推荐)
一种方法是从参数中删除“&”。像这样:
T& operator[](std::string key);
这样你请求的不是左值,而是右值。问题是当你发送一个值时,你不会发送 4 个字节的内存地址,而是 sizeof("Your string") 字节。重法..
创建一个 const 左值(推荐方式)
解决这个问题的最漂亮的方法是使参数为 const 左值(所谓的 rvalue reference
),向编译器承诺您不会尝试更改给定地址的这个函数里面的值。它看起来像这样:
T& operator[](const std::string &key);
现在您可以发送左值字符串和右值字符串。
放弃
这种方式不如第一种好,但绝对不如第二种好。您可以轻松地使用您的声明:
T& operator[](std::string &key);
并且当你传递一个值时,使用另一个字符串变量来存储该值,并在调用时使用这个变量:
Thread_map<std::string> map;
string key = "mkey";
map[key] = "value";
(不要那样做..只是知识的扩展)。
我基本上是在尝试为 std::map
创建一个线程安全的包装器 class。
由于我来自 C,我很难搞清楚 C++ 的所有细微差别。
我正在尝试覆盖 [] operator
以采用 std::string
参数将其传递给我的 std::map
成员。
根据 std::map::operator[]
的参考,这应该可以正常工作:
T& operator[]( const Key& key );
这是我的class:
thread_map.hpp
#ifndef THREAD_MAP_H
#define THREAD_MAP_H
#include <map>
#include <functional>
#include <mutex>
template <class T>class Thread_map
{
private:
std::map<std::string, T> map;
std::mutex map_mutex;
public:
~Thread_map();
T& at(size_t pos);
T& operator[](std::string &key);
size_t size() const;
bool empty() const;
void clear();
void insert(std::pair<std::string, T> pair);
T& erase(const std::string &key);
bool for_each(std::function<bool (Thread_map, std::string&, T&)> fun);
};
template<class T> Thread_map<T>::~Thread_map()
{
this->map.clear();
}
template<class T> T& Thread_map<T>::at(size_t pos)
{
T *value;
this->map_mutex.lock();
value = this->map.at(pos);
this->map_mutex.unlock();
return value;
}
template<class T> T& Thread_map<T>::operator[](std::string &key)
{
this->map_mutex.lock();
T &value = this->map[key];
this->map_mutex.unlock();
return value;
}
template<class T> size_t Thread_map<T>::size() const
{
size_t size;
this->map_mutex.lock();
size = this->map.size();
this->map_mutex.unlock();
return size;
}
template<class T> bool Thread_map<T>::empty() const
{
bool empty;
this->map_mutex.lock();
empty = this->map.empty();
this->map_mutex.unlock();
return empty;
}
template<class T> void Thread_map<T>::clear()
{
this->map_mutex.lock();
this->map.clear();
this->map_mutex.unlock();
}
template<class T> void Thread_map<T>::insert(std::pair<std::string, T> pair)
{
this->map_mutex.lock();
this->map.insert(pair);
this->map_mutex.unlock();
}
template<class T> T& Thread_map<T>::erase(const std::string &key)
{
T *value;
this->map_mutex.lock();
value = this->map.erase(key);
this->map_mutex.unlock();
return value;
}
template<class T> bool Thread_map<T>::for_each(std::function<bool
(Thread_map, std::string&, T&)> fun)
{
}
#endif
我将实现放入头文件中,因为我听说您使用模板 classes 来实现。我说得对吗? 我的问题是,当我尝试致电接线员时
Thread_map<std::string> map;
map["mkey"] = "value";
g++ 在 map["mkey"] 上抛出一个无效的初始化错误。
就我的理解而言,问题是 mkey
被编译为 std::string("mkey")
这只是值,而不是引用。
但是,为什么或如何执行以下操作?
std::map<std::string, std::string> map;
map["mkey"] = "value";
我的意思是我可以按值传递字符串,但这似乎效率不高。
引用需要一个可以修改的变量地址。对于左值字符串("some string"),没有可以修改值的地址。 我知道有一些方法可以解决这个问题:
删除引用(不推荐)
一种方法是从参数中删除“&”。像这样:
T& operator[](std::string key);
这样你请求的不是左值,而是右值。问题是当你发送一个值时,你不会发送 4 个字节的内存地址,而是 sizeof("Your string") 字节。重法..
创建一个 const 左值(推荐方式)
解决这个问题的最漂亮的方法是使参数为 const 左值(所谓的 rvalue reference
),向编译器承诺您不会尝试更改给定地址的这个函数里面的值。它看起来像这样:
T& operator[](const std::string &key);
现在您可以发送左值字符串和右值字符串。
放弃
这种方式不如第一种好,但绝对不如第二种好。您可以轻松地使用您的声明:
T& operator[](std::string &key);
并且当你传递一个值时,使用另一个字符串变量来存储该值,并在调用时使用这个变量:
Thread_map<std::string> map;
string key = "mkey";
map[key] = "value";
(不要那样做..只是知识的扩展)。