可以将std :: map创建为右值?

时间:2016-07-26 21:39:52

标签: c++ dictionary std stdmap rvalue

我不确定这是否是我的C ++语法错误,或者这是否是根本无法完成的事情。

我想定义一个将std :: map作为构造函数参数的类。然后我想通过传递一个“临时”(适当调用这个“rvalue”?)std :: map来创建该类的实例。即我不想创建一个左值std :: map,然后将其传递给构造函数。

这可以实现吗?我尝试了以下(注释行显示失败的尝试)

#include <map>
#include <string>
#include <iostream>

class Test
{
    public:
        Test(std::map<int,char>& rMap)
        {
            std::map<int,char>::iterator iter;

            for (iter = rMap.begin(); iter != rMap.end(); ++iter)
            {
                mMap[iter->first] = mMap[iter->second];
            }
        }
        virtual ~Test(){}

    protected:
        std::map<int, char> mMap;
};

int main()
{
    std::cout << "Hello world!" << std::endl;

    //Test test({1,'a'});                   // Compile error.
    //Test test(std::map<int,char>(1,'a')); // Also compile error.
    //Test test(std::map<int,char>{1,'a'}); // Yet again compile error.

    return 0;
}

这是我的编译器:

g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-11)

编译错误可以根据请求发布,但我不确定如果我的问题是语法错误它们是否有用。

谢谢。

4 个答案:

答案 0 :(得分:5)

待办事项

Test(std::map<int, char> rMap) : mMap(std::move(rMap)) {}

Test(std::map<int, char>&& rMap) : mMap(std::move(rMap)) {}

Test(const std::map<int, char>& rMap) : mMap(rMap) {}

临时不能绑定到非const l-value引用。

并将其用作

Test test({{1,'a'}});
Test test2({{1,'a'}, {2, 'b'}});

答案 1 :(得分:4)

是的,但您的构造函数采用左值引用。它必须是引用 - const或右值引用。

就像任何其他类型一样。

答案 2 :(得分:1)

#include <map>

class Test {
public:
    Test(std::map<int,char> const& cMap)
    {
        std::map<int,char>::const_iterator iter;
        for (iter = cMap.cbegin(); iter != cMap.cend(); ++iter)
        {
            mMap[iter->first] = mMap[iter->second];
        }
    }
    virtual ~Test() { }
protected:
    std::map<int, char> mMap;
};

int main() {
    Test test(std::map<int,char>({{1,'a'}, {2, 'b'}}));
    return 0;
}

一些解释:

  1. 如果要将临时对象(如Test(T))传递到其中,则需要Test(const T&)Test(T&&)std::map<int,char>()构造函数。不要忘记使用T&&构造函数。如果有疑问,请不要使用它们。
  2. 如果您使用const std::vector/map/list/...,则无法使用.begin().end()来迭代元素 - 请使用。 c begin()和。 c 结束()。此外,auto将变得更加容易。试试吧

    for (auto iter = rMap.cbegin(); iter != rMap.cend(); ++iter)
    

    代替

    std::map<int,char>::const_iterator iter;
    for (iter = rMap.cbegin(); iter != rMap.cend(); ++iter)
    
  3. 要初始化std::map,请使用“{{1,'a'}, {2, 'b'}} - {{key, value}, {second_key, second_value}, ...}这样的”双括号“初始值设定项,因为

    1)std::map有这个构造函数:

    map( std::initializer_list<value_type> init,
         const Compare& comp = Compare(),
         const Allocator& alloc = Allocator() );
    // see http://en.cppreference.com/w/cpp/container/map/map
    

    2)内括号{1,'a'}被解释为value_type构造函数调用。 value_type的{​​{1}}为std::map<int, char>

  4. P上。 S.不要忘记std::pair<int, char>std::map<int,char>()构造函数调用是相等的。这意味着您可以删除前括号:std::map<int,char>{}

答案 3 :(得分:0)

您应该使用:

class Test
{
public:
    Test(const std::map<int,char>& rMap) : mMap(rMap)
    {}
    Test(std::map<int,char>&& rMap) : mMap(std::move(rMap))
    {}
    virtual ~Test(){}
protected:
    std::map<int, char> mMap;
};

这提供了两个构造函数:一个采用const左值引用并将其内容复制到mMap,另一个采用右值引用并将其内容移动到mMap。这允许您使用命名的Test或临时的:

来构造std::map实例
int main()
{
    std::map<int,char> m{{1, 'a'}, {2,'b'}};
    Test t1{m};
    Test t2{{{1, 'a'}, {2, 'b'}}};
}

这样可以尽可能避免不必要的副本,但仍然允许您在需要时复制map