1

这是我的代码

#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 或 clang 3.1 和 --std=c++0x 在 Linux 上编译代码时,它输出 0 和 2。但是,当我在 Mac OS X 10.7.4 或 FreeBSD 9.0 上使用带有--std=c++0x 的clang 3.0 或clang 3.1,它输出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 时,我得到了一个编译错误,即使我注释了最后三行代码。这次问题与右值引用无关,而是来自 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.
4

2 回答 2

3

GCC 4.2 是古老的,所以它std::vector不支持右值引用。使用boost::move不会改变这一点,它不能神奇地将右值引用支持添加到不支持它的编译器 + 库中。这意味着它是复制而不是移动。

我怀疑当您在 Mac 上使用 Clang 时,它使用的是 GCC 4.2 中的旧标准库,即使编译器支持右值引用,它仍然不支持。你可以改用 libc++ 库吗,它应该支持 C++11 吗?

当您在 Linux 上使用 Clang 时,它使用 GCC 4.7 中的标准库,它支持 C++11。

NB Clang 3.1 和 GCC 4.7 都支持-std=c++11而不是-std=c++0x,我认为 Clang 3.0 也支持。如果您的所有编译器都为该选项使用较新的名称,您不妨使用它。

于 2012-06-16T10:52:42.333 回答
0
rvalue_reference boost::move(input_reference)

此函数提供了一种在具有右值引用的编译器中将引用转换为右值引用的方法。对于其他编译器转换T&::boost::rv<T>&,以便激活移动仿真。

如果 std::vector::operator=(boost::rv&) 未定义,则它可能会退回到常规复制构造。我认为你必须做一些特别的事情来处理 boost::rvs 的课程

于 2012-06-16T06:55:54.597 回答