Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这是使用移动引用和唯一\u ptr的正确方法吗? 我几乎没有使用C++移动功能,所以我不自信我所做的是正确的。如果有人能仔细阅读我的代码并指出我犯的任何错误,我将不胜感激_C++_C++11 - Fatal编程技术网

这是使用移动引用和唯一\u ptr的正确方法吗? 我几乎没有使用C++移动功能,所以我不自信我所做的是正确的。如果有人能仔细阅读我的代码并指出我犯的任何错误,我将不胜感激

这是使用移动引用和唯一\u ptr的正确方法吗? 我几乎没有使用C++移动功能,所以我不自信我所做的是正确的。如果有人能仔细阅读我的代码并指出我犯的任何错误,我将不胜感激,c++,c++11,C++,C++11,这个想法是创建一个由key存储的资源地图。资源可能是不可复制和不可移动的 另外,我的类是否需要构造函数和析构函数定义 谢谢 #define TYPE(x) std::identity<decltype(x)>::type namespace General { template<class T> std::string ToString(const T& x) { std::ostringstream ss;

这个想法是创建一个由key存储的资源地图。资源可能是不可复制和不可移动的

另外,我的类是否需要构造函数和析构函数定义

谢谢

#define TYPE(x) std::identity<decltype(x)>::type

namespace General
{
    template<class T>
    std::string ToString(const T& x)
    {
        std::ostringstream ss;
        ss << x;
        return ss.str();
    }
}

namespace General
{
    template<class T, class KEY = std::string>
    class ResourceManager
    {
    public:
        typedef T ResourceType;
        typedef KEY KeyType;

        void Load(const KeyType& key, std::unique_ptr<ResourceType>&& resource);
        const ResourceType& Read(const KeyType& key) const;
        ResourceType& Modify(const KeyType& key);
        void Unload(const KeyType& key);
        std::unique_ptr<ResourceType>&& Release(const KeyType& key);
        void UnloadAll();

    private:
        std::map<KeyType, std::unique_ptr<ResourceType>> data;
    };
}

template<class T, class KEY>
void General::ResourceManager<T, KEY>::Load(const KeyType& key, std::unique_ptr<ResourceType>&& resource)
{
    auto find_it = data.lower_bound(key);
    if (find_it != data.end() && ! (data.key_comp()(key, find_it->first)))
    {
        throw std::runtime_error(General::ToString(key) + " already exists!");
    }
    else
    {
        data.insert(find_it, TYPE(data)::value_type(key, std::move(resource)));
    }
}

template<class T, class KEY>
const typename General::ResourceManager<T, KEY>::ResourceType& General::ResourceManager<T, KEY>::Read(const KeyType& key) const
{
    auto find_it = data.find(key);
    if (find_it == data.end())
    {
        throw std::runtime_error(General::ToString(key) + " could not be found!");
    }
    else
    {
        return *find_it->second;
    }
}

template<class T, class KEY>
typename General::ResourceManager<T, KEY>::ResourceType& General::ResourceManager<T, KEY>::Modify(const KeyType& key)
{
    auto find_it = data.find(key);
    if (find_it == data.end())
    {
        throw std::runtime_error(General::ToString(key) + " could not be found!");
    }
    else
    {
        return *find_it->second;
    }
}

template<class T, class KEY>
void General::ResourceManager<T, KEY>::Unload(const KeyType& key)
{
    auto find_it = data.find(key);
    if (find_it == data.end())
    {
        throw std::runtime_error(General::ToString(key) + " could not be found!");
    }
    else
    {
        data.erase(find_it);
    }
}

template<class T, class KEY>
std::unique_ptr<typename General::ResourceManager<T, KEY>::ResourceType>&& General::ResourceManager<T, KEY>::Release(const KeyType& key)
{
    auto find_it = data.find(key);
    if (find_it == data.end())
    {
        throw std::runtime_error(General::ToString(key) + " could not be found!");
    }
    else
    {
        auto resource = std::move(find_it->second);
        data.erase(find_it);
        return std::move(resource);
    }
}

template<class T, class KEY>
void General::ResourceManager<T, KEY>::UnloadAll()
{
    data.clear();
}
定义类型(x)std::identity::TYPE 命名空间常规 { 模板 标准::字符串到字符串(常量T&x) { std::ostringstream ss; (第一次) { 抛出std::runtime_错误(常规::ToString(键)+“已存在!”); } 其他的 { data.insert(find_it,TYPE(数据)::value_TYPE(key,std::move(resource)); } } 模板 常量类型名称常规::ResourceManager::ResourceType&常规::ResourceManager::读取(常量键类型&键)常量 { 自动查找=data.find(键); if(find_it==data.end()) { 抛出std::runtime_错误(常规::ToString(键)+“找不到!”); } 其他的 { 返回*查找它->秒; } } 模板 typename General::ResourceManager::ResourceType&General::ResourceManager::Modify(常量键类型&键) { 自动查找=data.find(键); if(find_it==data.end()) { 抛出std::runtime_错误(常规::ToString(键)+“找不到!”); } 其他的 { 返回*查找它->秒; } } 模板 void General::ResourceManager::Unload(常量键类型和键) { 自动查找=data.find(键); if(find_it==data.end()) { 抛出std::runtime_错误(常规::ToString(键)+“找不到!”); } 其他的 { 数据。擦除(找到它); } } 模板 std::unique_ptr&General::ResourceManager::Release(const-KeyType&key) { 自动查找=data.find(键); if(find_it==data.end()) { 抛出std::runtime_错误(常规::ToString(键)+“找不到!”); } 其他的 { 自动资源=std::move(查找它->秒); 数据。擦除(找到它); 返回std::移动(资源); } } 模板 void General::ResourceManager::UnloadAll() { data.clear(); }
下面是一段简化的代码,它演示了您的情况以及如何按照惯用方式编写代码:

std::map<int, std::unique_ptr<Foo>> m;

void add_to_map(int key, std::unique_ptr<Foo> val)
{
    m[key] = std::move(val);
}
std::map m;
void add_to_map(int key,std::unique_ptr val)
{
m[key]=std::move(val);
}
用法:

add_to_map(1, std::unique_ptr<Foo>(new Foo(1, 2, 3)));

std::unique_ptr<Foo> p(new Foo(true, 'x'));
p->mutate();
add_to_map(std::move(p));
std::unique_ptr<Foo> p(new Foo(true, 'x'));

add_maybe(p);

if (p) { /* we still own the resource            */ }
else   { /* the resource is now owned by the map */ }
add_-to_-map(1,std::unique_-ptr(新的Foo(1,2,3));
std::unique_ptr p(新的Foo(true,'x'));
p->mutate();
将_添加到_映射(std::move(p));
基本上,通过值传递唯一指针(或任何其他仅可移动的类型),然后从中移动


我遇到的一种特殊情况是,您希望有条件地获得对象的所有权。在这种情况下,请通过引用传递唯一指针,然后检查它:

void add_maybe(std::unique_ptr<Foo> & val)
{
    if (rand() % 2 == 0)
    {
        m[12] = std::move(val);
    }
}
void add\u maybe(std::unique\u ptr&val)
{
如果(rand()%2==0)
{
m[12]=std::move(val);
}
}
用法:

add_to_map(1, std::unique_ptr<Foo>(new Foo(1, 2, 3)));

std::unique_ptr<Foo> p(new Foo(true, 'x'));
p->mutate();
add_to_map(std::move(p));
std::unique_ptr<Foo> p(new Foo(true, 'x'));

add_maybe(p);

if (p) { /* we still own the resource            */ }
else   { /* the resource is now owned by the map */ }
std::unique_ptr p(新的Foo(true,'x');
加上_-maybe(p);
如果(p){/*我们仍然拥有资源*/}
否则{/*该资源现在由映射所拥有*/}

更新:要从地图中释放对象,请按值返回:

std::unique_ptr<Foo> release(int key)
{
    auto it = m.find(key);
    return it == m.end() ? { } : std::move(it->second);
}
std::唯一的ptr发布(int键)
{
自动it=m.find(键);
返回it==m.end()?{}:std::move(it->second);
}

那么函数的调用者应该显式地将他的对象移动到my value参数吗?@NeilKirk:如果调用者有一个左值,那么是的。否则它是隐式的,不需要额外的代码(如第一个使用示例中所示)。该示例应该是
添加到映射(std::make_unique(1,2,3))
确实如此,尽管这需要C++14。释放函数的返回类型如何?也是按值,
std::uniqueptr
。基本上,所有内容都是按值进行的,除了一些例外。