可以创建 std::map 作为右值

Possible to create std::map as rvalue?

本文关键字:map 创建 std      更新时间:2023-10-16

我不确定这是否是我的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)

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

谢谢。

do

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) {}

临时不能绑定到非常量 l 值引用。

并将其用作

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

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

就像任何其他类型一样。

#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. 如果你想将临时对象(如std::map<int,char>()(传递到其中,你需要Test(T)Test(const T&)Test(T&&)构造函数。不要忘记构造函数T&&用途。如有疑问,请不要使用它们。
  2. 如果您使用const std::vector/map/list/...则不能使用.begin().end()来循环访问元素 - 使用 .cbegin(( 和 .cend((。此外,随着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_typevalue_type std::map<int, char>std::pair<int, char>.

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

你应该使用:

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。 这允许您使用命名std::map或临时实例构造Test实例:

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

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