我有一个程序从文件中读取如下所示的行:
...
name1 (123)
name2 (345)
...
然后,它将每一行作为 MyClass 的对象存储在名为 namelist 的地图中。 namelist 的关键是对象的名称,该值是对象本身。在代码的第一个版本中, namelist 的类型为 map<字符串,MyClass> ,并且对象在循环中创建为 MyClass obj; (和ofc all' - >'是'。'。但是这只创建了一个地图相同的对象,为什么?我读过你很少需要在c ++中对象使用'new'。为什么我需要它?
ifstream myfile ("input.txt");
map<string,MyClass*> namelist;
string line;
while ( getline(myfile,line) ) {
istringstream iss(line);
string word;
while (iss>>word) {
MyClass* obj = new MyClass;
obj->name = word;
iss>>word;
sscanf(word.c_str(),"(%d)",&obj->number);
namelist.insert( pair<string,MyClass*>(obj->name,obj) );
}
}
myfile.close();
答案 0 :(得分:1)
您不需要new
。只需执行map<string,MyClass> namelist
和MyClass obj;
(默认构造函数w /堆栈分配)
new
用于在堆上分配对象,并且必须使用delete
显式释放数据。相反,只需使地图保持MyClass
个对象而不是指向这些对象的指针。 map对象会将对象复制到堆上,并为您处理释放。
答案 1 :(得分:0)
您不需要new
因为std::map
已经负责动态分配。
std::map<std::string, MyClass> namelist;
您甚至不需要先创建临时变量并将其插入到地图中,这会创建一个不必要的副本。相反,直接在地图中创建对象将更有效。
以下技术要求MyClass
只有默认构造函数。除了提高效率外,此技术还允许您使用没有复制构造函数(例如std::ifstream
)的类作为地图值。
要获得与std::map::insert()
相同的语义,需要显式调用find()
。如果您可以接受重复键覆盖映射中现有对象的事实,则可以通过删除if
来简化代码。
// Check if the key does not exist yet.
if (namelist.find(word) == namelist.end()){
// Default-construct object within map and get a reference to it.
MyClass& obj = namelist[word];
// Do something with inserted obj...
obj.name = word;
}
如果您的类具有构造函数,其中包含一个或多个参数,您希望在就地构建期间调用它,则需要C ++ 11功能,即std::map::emplace()
。
// Construct MyClass within the map, if the key does not exist yet.
// Pass arguments arg1, arg2, argN to the constructor of MyClass.
auto res = namelist.emplace(arg1, arg2, argN);
if (res.second){ // new object inserted?
// Get a reference to the inserted object.
MyClass& obj = *res.first;
// Do something with inserted obj...
obj.name = word;
}