可以将 std::map 创建为右值吗?
Possible to create std::map as rvalue?
我不确定这是我的 C++ 语法错误,还是根本无法完成。
我想定义一个 class,它将 std::map 作为构造函数参数。然后我想通过传递 "temporary"(适合称呼此 "rvalue"?)std::map 来创建 class 的实例。 IE。我不想创建左值 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)
可以根据要求发布编译错误,但我不确定如果我的问题是语法问题,它们是否有用。
谢谢。
是的,但是您的构造函数采用左值引用。它必须是对 const
的引用或右值引用。
就像任何其他类型一样。
做
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 左值引用。
并将其用作
Test test({{1,'a'}});
Test test2({{1,'a'}, {2, 'b'}});
#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;
}
一些解释:
- 如果您想将临时对象(如
std::map<int,char>()
)传递给它,您需要Test(T)
、Test(const T&)
或Test(T&&)
构造函数。不要忘记 T&&
构造函数的用途。如果有疑问,请不要使用它们。
如果您使用 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)
要初始化 std::map
使用 "double-bracket" 初始化器,如 {{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
构造函数调用。 std::map<int, char>
的 value_type
是 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
的副本。
我不确定这是我的 C++ 语法错误,还是根本无法完成。
我想定义一个 class,它将 std::map 作为构造函数参数。然后我想通过传递 "temporary"(适合称呼此 "rvalue"?)std::map 来创建 class 的实例。 IE。我不想创建左值 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)
可以根据要求发布编译错误,但我不确定如果我的问题是语法问题,它们是否有用。
谢谢。
是的,但是您的构造函数采用左值引用。它必须是对 const
的引用或右值引用。
就像任何其他类型一样。
做
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 左值引用。
并将其用作
Test test({{1,'a'}});
Test test2({{1,'a'}, {2, 'b'}});
#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;
}
一些解释:
- 如果您想将临时对象(如
std::map<int,char>()
)传递给它,您需要Test(T)
、Test(const T&)
或Test(T&&)
构造函数。不要忘记T&&
构造函数的用途。如果有疑问,请不要使用它们。 如果您使用
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)
要初始化
std::map
使用 "double-bracket" 初始化器,如{{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
构造函数调用。std::map<int, char>
的value_type
是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
的副本。