是否std::is_move_constructible<T>::value == true
暗示T
有一个可用的移动构造函数?如果是这样,它的默认行为是什么?
考虑以下情况:
struct foo {
int* ptr;
};
int main() {
{
std::cout << std::is_move_constructible<foo>::value << '\n';
foo f;
f.ptr = (int*)12;
foo f2(std::move(f));
std::cout << f.ptr << ' ' << f2.ptr << '\n';
}
return 0;
}
输出是:
1
0000000C 0000000C
我认为f.ptr
应该是nullptr
。所以在这种情况下,
f2
移动构建了吗?- 如果是这样,不应该使右值无效吗?
- 我怎么知道一个类的实例是否可以正确移动构造(使旧实例无效)?
(我正在使用 VS11。)
更新
移动构造函数的默认行为与复制构造函数相同,是否正确?如果是真的,
- 我们总是期望一个移动 ctor 窃取被移动对象的资源,而默认的行为并不像预期的那样,那么拥有一个默认的移动 ctor 有什么意义呢?
- 我怎么知道一个类是否有一个自定义的移动构造函数(可以保证行为正确)?
当我声明一个时,它似乎foo f2(std::move(f));
调用了复制 ctor,请参阅:
struct foo {
int* ptr;
foo() {}
foo(const foo& other) {
std::cout << "copy constructed\n";
}
};
int main() {
{
std::cout << std::is_move_constructible<foo>::value << '\n';
foo f;
foo f2(std::move(f));
}
system("pause");
return 0;
}
现在输出是:
1
copy constructed
如果foo
有一个移动构造函数,那么不会foo f2(std::move(f))
调用它吗?
所以现在我的问题是:如何知道一个类是否有一个移动 ctor,如果有,我该如何明确地调用它?
我想做的是……</h2>
template<typename T, bool has_move_ctor>
struct MoveAux;
template<typename T>
struct MoveAux<T, true> {
static void doMove(T* dest, T* src) {
new(dest) T(std::move(*src)); //move ctor
}
};
template<typename T>
struct MoveAux<T, false> {
static void doMove(T* dest, T* src) {
new(dest) T(*src); //copy ctor
src->~T();
}
};
template<typename T>
inline doMove(T* dest, T* src) {
MoveAux<T,/*a trait*/>::doMove(dest, src);
}
template<typename T, bool has_move_ctor>
struct MoveAux;
template<typename T>
struct MoveAux<T, true> {
static void doMove(T* dest, T* src) {
new(dest) T(std::move(*src)); //move ctor
}
};
template<typename T>
struct MoveAux<T, false> {
static void doMove(T* dest, T* src) {
new(dest) T(*src); //copy ctor
src->~T();
}
};
template<typename T>
inline doMove(T* dest, T* src) {
MoveAux<T,/*a trait*/>::doMove(dest, src);
}
所以我认为std::is_move_constructible<T>::value
可以传递给模板,而现在我看到这个特征只关心是否T t(T())
是一个有效的表达式,它可能会调用T::T(const T&)
. 现在假设这T
是一个自定义类,那么我希望上面的模板表现得像:
- 如果我不声明移动 ctor,我希望该模板方法调用
MoveAux<T,false>::doMove
. - 如果我声明了一个,我需要它调用
MoveAux<T,true>::doMove
.
有可能完成这项工作吗?