我有以下问题与迭代使用std::map
定义的字符串的关联数组有关。
-- snip --
class something
{
//...
private:
std::map<std::string, std::string> table;
//...
}
在构造函数中,我使用与字符串数据相关联的字符串键对填充表。在其他地方,我有一个方法toString
,它返回一个字符串对象,该对象包含表对象中包含的所有键和相关数据(作为键=数据格式)。
std::string something::toString()
{
std::map<std::string, std::string>::iterator iter;
std::string* strToReturn = new std::string("");
for (iter = table.begin(); iter != table.end(); iter++) {
strToReturn->append(iter->first());
strToReturn->append('=');
strToRetunr->append(iter->second());
//....
}
//...
}
当我尝试编译时,我收到以下错误:
error: "error: no match for call to ‘(std::basic_string<char,
std::char_traits<char>, std::allocator<char> >) ()’".
有人可以向我解释遗失的是什么,我做错了什么?
在hash_map
的情况下,我只发现了一些关于类似问题的讨论,其中用户必须定义散列函数才能将hash_map
与std::string
对象一起使用。在我的情况下也可能是类似的东西吗?
答案 0 :(得分:73)
您的主要问题是您在迭代器中调用了一个名为first()
的方法。您打算做的是使用名为first
的属性:
...append(iter->first) rather than ...append(iter->first())
作为一种风格问题,您不应该使用new
来创建该字符串。
std::string something::toString()
{
std::map<std::string, std::string>::iterator iter;
std::string strToReturn; //This is no longer on the heap
for (iter = table.begin(); iter != table.end(); ++iter) {
strToReturn.append(iter->first); //Not a method call
strToReturn.append("=");
strToReturn.append(iter->second);
//....
// Make sure you don't modify table here or the iterators will not work as you expect
}
//...
return strToReturn;
}
编辑: facildelembrar指出(在评论中)现代C ++中你现在可以重写循环
for (auto& item: table) {
...
}
答案 1 :(得分:19)
不要编写toString()
方法。这不是Java。为您的班级实施流操作符。
首选使用标准算法而不是编写自己的循环。在这种情况下,std::for_each()
为您想要做的事提供了一个很好的界面。
如果您必须使用循环,但不打算更改数据,请选择const_iterator
而不是iterator
。这样,如果您意外尝试更改值,编译器将发出警告。
然后:
std::ostream& operator<<(std::ostream& str,something const& data)
{
data.print(str)
return str;
}
void something::print(std::ostream& str) const
{
std::for_each(table.begin(),table.end(),PrintData(str));
}
然后,当您想要打印它时,只需流式传输对象:
int main()
{
something bob;
std::cout << bob;
}
如果您确实需要对象的字符串表示,则可以使用lexical_cast
。
int main()
{
something bob;
std::string rope = boost::lexical_cast<std::string>(bob);
}
需要填写的详细信息。
class somthing
{
typedef std::map<std::string,std::string> DataMap;
struct PrintData
{
PrintData(std::ostream& str): m_str(str) {}
void operator()(DataMap::value_type const& data) const
{
m_str << data.first << "=" << data.second << "\n";
}
private: std::ostream& m_str;
};
DataMap table;
public:
void something::print(std::ostream& str);
};
答案 2 :(得分:4)
将您的追加电话改为
...append(iter->first)
和
... append(iter->second)
此外,该行
std::string* strToReturn = new std::string("");
在堆上分配一个字符串。如果您打算实际返回指向此动态分配字符串的指针,则应将返回值更改为std :: string *。
或者,如果您不想担心在堆上管理该对象,请将本地声明更改为
std::string strToReturn("");
并更改'append'调用以使用引用语法...
strToReturn.append(...)
而不是
strToReturn->append(...)
请注意,这将在堆栈上构造字符串,然后将复制到返回变量中。这有性能影响。
答案 3 :(得分:2)
iter->first
和iter->second
是变量,您试图将它们称为方法。
答案 4 :(得分:2)
请注意,取消引用std :: map :: iterator的结果是std::pair。 first
和second
的值不是函数,它们是变量。
变化:
iter->first()
到
iter->first
与iter->second
同上。
答案 5 :(得分:1)
使用:
std::map<std::string, std::string>::const_iterator
代替:
std::map<std::string, std::string>::iterator
答案 6 :(得分:0)
在c ++ 11中你可以使用
for ( auto iter : table ) {
key=iter->first();
value=iter->second();
}
答案 7 :(得分:0)
另一个有价值的优化是STL 字符串类的 c_str()成员,它返回一个不可变的空终止字符串,可以作为 LPCTSTR传递,e。例如,一个需要LPCTSTR的自定义函数。虽然我没有通过析构函数来确认它,但我怀疑字符串类会查看它创建副本的内存。