这是我的代码
#include <iostream>
#include <vector>
int main()
{
std::vector<size_t> v1, v2;
v1.push_back(3);
v1.push_back(4);
v2 = static_cast<std::vector<size_t>&&>(v1);
std::cout << v1.size() << '\n';
std::cout << v2.size() << '\n';
}
当我使用GCC 4.7.0或使用--std = c ++ 0x的clang 3.1在Linux上编译代码时,它输出0和2。 但是,当我使用clang 3.0或clang 3.1和--std = c ++ 0x在Mac OS X 10.7.4或FreeBSD 9.0上编译代码时,输出2和2.我的Mac OS X和FreeBSD上的GCC是v4.2.1,不支持--std = c ++ 0x。所以我使用了Boost.Move:
#include <boost/move/move.hpp>
v2 = boost::move(v1);
当我使用带有-I~ / boost_1_49_0的GCC 4.2.1在Mac OS X上编译代码时,它仍然输出2和2.
更新:当我添加--stdlib = libc ++时,代码输出0和2.右值引用似乎正常工作。但是,当我将矢量类型从size_t更改为string时,我得到了编译错误,即使我评论了最后三行代码。这次问题与Rvalue引用无关,但来自push_back()函数。当我删除--stdlib = libc ++时,它可以通过编译。
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> v1, v2;
v1.push_back("hello");
/*
v2 = static_cast<std::vector<std::string>&&>(v1);
std::cout << v1.size() << '\n';
std::cout << v2.size() << '\n';
*/
}
哪个铿锵
/uac/gds/hjli/clang+llvm-3.1-x86_64-apple-darwin11/bin/clang
clang ++ --std = c ++ 11 --stdlib = libc ++ rval.cpp
In file included from rval.cpp:1:
In file included from /usr/include/c++/v1/iostream:38:
In file included from /usr/include/c++/v1/ios:216:
In file included from /usr/include/c++/v1/__locale:15:
/usr/include/c++/v1/string:1952:10: error: overload resolution selected
implicitly-deleted copy assignment operator
__r_ = _STD::move(__str.__r_);
^
/usr/include/c++/v1/string:1942:9: note: in instantiation of member function
'std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >::__move_assign' requested here
__move_assign(__str, true_type());
^
/usr/include/c++/v1/string:1961:5: note: in instantiation of member function
'std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >::__move_assign' requested here
__move_assign(__str, integral_constant<bool,
^
/usr/include/c++/v1/algorithm:1595:19: note: in instantiation of member function
'std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >::operator=' requested here
*__result = _STD::move(*__first);
^
/usr/include/c++/v1/algorithm:1619:12: note: in instantiation of function
template specialization 'std::__1::__move<std::__1::basic_string<char> *,
std::__1::basic_string<char> *>' requested here
return _STD::__move(__unwrap_iter(__first), __unwrap_iter(__last),...
^
/usr/include/c++/v1/__config:153:14: note: expanded from macro '_STD'
#define _STD std::_LIBCPP_NAMESPACE
^
/usr/include/c++/v1/__split_buffer:557:22: note: in instantiation of function
template specialization 'std::__1::move<std::__1::basic_string<char> *,
std::__1::basic_string<char> *>' requested here
__end_ = _STD::move(__begin_, __end_, __begin_ - __d);
^
/usr/include/c++/v1/__config:153:14: note: expanded from macro '_STD'
#define _STD std::_LIBCPP_NAMESPACE
^
/usr/include/c++/v1/vector:1289:13: note: in instantiation of member function
'std::__1::__split_buffer<std::__1::basic_string<char>,
std::__1::allocator<std::__1::basic_string<char> > &>::push_back'
requested here
__v.push_back(_STD::move(__x));
^
rval.cpp:10:5: note: in instantiation of member function
'std::__1::vector<std::__1::basic_string<char>,
std::__1::allocator<std::__1::basic_string<char> > >::push_back' requested
here
v1.push_back("nice");
^
/usr/include/c++/v1/memory:1941:5: note: copy assignment operator is implicitly
deleted because '__compressed_pair<std::__1::basic_string<char,
std::__1::char_traits<char>, std::__1::allocator<char> >::__rep,
std::__1::allocator<char> >' has a user-declared move constructor
__compressed_pair(__compressed_pair&& __p)
^
1 error generated.
答案 0 :(得分:3)
GCC 4.2很古老,因此它的std::vector
不支持右值引用。使用boost::move
不会改变它,它不能神奇地将rvalue引用支持添加到不支持它的编译器+库。这意味着它执行复制而非移动。
我怀疑当你在Mac上使用Clang时,它正在使用GCC 4.2中的旧标准库,即使编译器确实如此,仍然不支持右值引用。您可以使用libc ++库,它应该支持C ++ 11吗?
在Linux上使用Clang时,它使用GCC 4.7中的标准库,它支持C ++ 11。
N.B。 Clang 3.1和GCC 4.7都支持-std=c++11
而不是-std=c++0x
,我认为Clang 3.0也是如此。如果您的所有编译器都使用该选项的新名称,您也可以使用它。
答案 1 :(得分:0)
rvalue_reference boost::move(input_reference)
此函数提供了一种在带有右值引用的编译器中将引用转换为右值引用的方法。对于其他编译器,将
T&
转换为::boost::rv<T>&
,以便激活移动仿真。
如果未定义std :: vector :: operator =(boost :: rv&amp;),则可能会回退到常规复制构造。我认为你必须做一些特别的事情才能让一个类处理boost :: rvs