当 std::map::insert 找到该元素时,它仍构造该对象的实例.我怎样才能阻止这种情况
when std::map::insert finds the element, it still constructs an instance of the object. How can I stop this?
我有一个 std::map 对象的实例构建成本非常高。(在现实生活中,它们需要多次访问数据库。
我想访问地图的某个元素,或者如果它不存在,则创建它。这听起来像是 std::map::insert 的工作,除了不必要地构造昂贵的对象,然后在元素存在时丢弃。举例说明:
#include <iostream>
#include <map>
#include <string>
struct CexpensiveObject
{
CexpensiveObject(const char* args="default"):args_(args)
{
std::cout << "Constructor: CexpensiveObject(" << args << ")" << std::endl;
}
CexpensiveObject( const CexpensiveObject& other )
{
std::cout << "Copy Constructor: CexpensiveObject other.args_ = " << other.args_ << "." << std::endl;
args_ = other.args_;
}
~CexpensiveObject()
{
std::cout << "Destructor: CexpensiveObject args_ = " << args_ << "." << std::endl;
}
const char* args_;
};
// entry point
int main()
{
typedef std::map<std::string, CexpensiveObject> mymaptype;
mymaptype mymap;
std::pair<mymaptype::iterator, bool> insertionResult;
std::cout << "First insertion" << std::endl;
insertionResult = mymap.insert( mymaptype::value_type( "foobar", CexpensiveObject("first") ) );
std::cout << "Was it inserted? " << (insertionResult.second?"yes":"no") << std::endl;
std::cout << "Second insertion" << std::endl;
insertionResult = mymap.insert( mymaptype::value_type("foobar", CexpensiveObject("second") ) );
std::cout << "Was it inserted? " << (insertionResult.second?"yes":"no") << std::endl;
}
结果:
First insertion
Constructor: CexpensiveObject(first)
Copy Constructor: CexpensiveObject other.args_ = first.
Copy Constructor: CexpensiveObject other.args_ = first.
Destructor: CexpensiveObject args_ = first.
Destructor: CexpensiveObject args_ = first.
Was it inserted? yes
Second insertion
Constructor: CexpensiveObject(second)
Copy Constructor: CexpensiveObject other.args_ = second.
Destructor: CexpensiveObject args_ = second.
Destructor: CexpensiveObject args_ = second.
Was it inserted? no
Destructor: CexpensiveObject args_ = first.
复制和销毁比我预期的要多,但至关重要的是,如果 ma 中存在具有相同键的元素,则会构造一个实例 CexpensiveObject,然后丢弃。
我是否误用了 std::map::insert,或者我是否必须在实例化 CexpensiveObject 实例之前使用 std::map::find 来检查是否存在具有相同键的元素?
它是在
你到达insert
之前构建的,当你调用CexpensiveObject("second")
时。你正在传递无关的物体!(然后在将value_type
传递给insert
时将其复制。
代替insert
,使用 find
。如果您在所需键处找到该项目,那么您就完成了。如果没有,则插入它。
auto it = mymap.find("foobar");
if (it == mymap.end())
mymap.insert(mymaptype::value_type("foobar", CexpensiveObject("second")));
如果对象已经存在,使用 find 检查是否应插入元素以节省一些工作。
可悲的是map::insert多次调用您的复制构造函数。如果这不可访问,并且您可以使用 c++11,请查看 map::emplace_insert。如果必须使用 C++03,IIRC 提升容器有一个映射,该映射使用内部提升移动来模拟移动语义。
相关文章:
- 对象实例化调用构造函数的次数太多
- C++ 中的基本单一实例对象
- 在 C++ 中,类实例对象 do memcpy 总是崩溃
- C++:在函数中使用当前实例(对象)
- 单一实例对象是否通过线程安全返回shared_ptr
- std::system 实例化单一实例对象时的异常
- 使用unique_ptr的单一实例对象
- 如果已创建 mongocxx::实例对象,则无法创建该对象
- 单一实例对象的未解决外部符号链接错误
- 实例对象如何查看函数的对象参数的私有成员?
- 在C++中调用单一实例对象的正确方法
- 声明模板化实例对象的函数指针
- 如何在"boost::function"中访问类实例(对象)指针?
- 删除单一实例对象 cpp 时出现内存泄漏
- 从 EXE 和 DLL 访问单一实例对象中的成员变量
- 如何在 C++11 中将 vector 与引用类型实例对象一起使用
- 为什么在构造函数退出时创建新的实例(对象)
- "类实例对象"未在此范围内声明
- c++实例对象的函数指针
- 如何正确存储多个实例对象