gpt4 book ai didi

c++ - 这种在 C++03 中模拟 move 语义的方法有多安全?

转载 作者:可可西里 更新时间:2023-11-01 16:42:31 25 4
gpt4 key购买 nike

使用 this answer , 我发明了自己的基于 swap 的 C++03 模拟 move 语义的方法。

首先,我检测 move 语义(即 C++03 的可用性):

#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) ||  \
defined(_MSC_VER) && _MSC_VER >= 1600
#define HAS_MOVE_SEMANTICS 1
#elif defined(__clang)
#if __has_feature(cxx_rvalue_references)
#define HAS_MOVE_SEMANTICS 1
#else
#define HAS_MOVE_SEMANTICS 0
#endif
#else
#define HAS_MOVE_SEMANTICS 0
#endif

然后我有条件地定义一个名为move的宏:

#if !HAS_MOVE_SEMANTICS
#include <algorithm>
namespace _cpp11_detail
{
template<bool B, class T = void> struct enable_if;
template<class T> struct enable_if<false, T> { };
template<class T> struct enable_if<true, T> { typedef T type; };
template<class T>
inline char (&is_lvalue(
T &, typename std::allocator<T>::value_type const volatile &))[2];
inline char (&is_lvalue(...))[1];
template<bool LValue, class T>
inline typename enable_if<!LValue, T>::type move(T v)
{ T r; using std::swap; swap(r, v); return r; }
template<bool LValue, class T>
inline typename enable_if<LValue, T>::type move(T &v)
{ T r; using std::swap; swap(r, v); return r; }
template<bool LValue, class T>
inline typename enable_if<LValue, T>::type const &move(T const &v)
{ return v; }
}
using _cpp11_detail::move;
namespace std { using _cpp11_detail::move; }
// Define this conditionally, if C++11 is not supported
#define move(...) move< \
(sizeof((_cpp11_detail::is_lvalue)((__VA_ARGS__), (__VA_ARGS__))) != 1) \
>(__VA_ARGS__)
#endif

然后我这样使用它:

#include <vector>

std::vector<int> test(std::vector<int> v) { return std::move(v); }

int main()
{
std::vector<int> q(5, 5);
int x = 5;
int y = std::move(x);
std::vector<int> qq = test(std::move(test(std::move(q))));
}

我的问题是,这种方法在实践中安全如何?(假设它编译正常)

  1. 是否有任何实际场景可能无法在 C++03 中正常工作但在 C++11 中不能正常工作?

  2. 相反的情况如何——它能否在 C++11 中正常工作但在 C++03 中失败?

(注意:我正在寻找一个实用的答案,而不是一个语言律师的答案。我知道在 namespace std 中定义新成员在技术上是未定义的,但实际上这不会在任何编译器上引起问题,因此我认为出于这个问题的目的,我不值得担心。我担心诸如意外悬挂引用等情况。)

最佳答案

move 不会 move ,但您的move 会 move 。这意味着在 C++11 中,表达式上的 std::move 不会在任何地方赋值,或者使用者不会修改数据。你的。

更糟糕的是,您的move 会阻塞 rvo/nrvo,就像 C++11 一样。在 C++11 中,来自 test 的 return 语句将不是一个好主意,因为返回值将被隐式地 moveed。在 C++03 中,由于 nrvo 在参数上被阻塞,因此它是最佳的。所以两者的用途是不同的。

您的 std::move 返回值会经历引用生命周期延长,而 C++11 中的返回值不会。代码必须在两者中都经过全面测试。

关于c++ - 这种在 C++03 中模拟 move 语义的方法有多安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20742807/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com