是什么原因导致移动分配运算符未被调用



我正在处理自己的智能指针,遇到了一些奇怪的问题。没有调用移动分配运算符。所以我写了一个测试课,并且能够重现这个问题。移动分配运算符不会被调用,但会发生复制分配(即使没有复制分配运算符(。

这是我的测试班

#include <utility>
#include <iostream>
struct tag_t {};
constexpr tag_t tag {};
template <typename T>
struct Foo {
Foo() noexcept
: val{} {
std::cout << "Default constructn";
}
template <typename U>
Foo(tag_t, const U &val) noexcept
: val{val} {
std::cout << "Construct " << val << 'n';
}
~Foo() noexcept {
std::cout << "Destruct " << val << 'n';
}
template <typename U>
Foo(Foo<U> &&other) noexcept
: val{std::exchange(other.val, U{})} {
std::cout << "Move construct " << val << 'n';
}
template <typename U>
Foo &operator=(Foo<U> &&other) noexcept {
std::cout << "Move assign " << other.val << 'n';
val = std::exchange(other.val, U{});
return *this;
}
T val;
};

这些是测试

int main() {
{
Foo<int> num;
std::cout << "Value " << num.val << 'n';
num = {tag, 5};
std::cout << "Value " << num.val << 'n';
}
std::cout << 'n';
{
Foo<int> num;
std::cout << "Value " << num.val << 'n';
num = Foo<int>{tag, 5};
std::cout << "Value " << num.val << 'n';
}
return 0;
}

运行测试后,我得到了以下结果

Default construct
Value 0
Construct 5
Destruct 5
Value 5
Destruct 5
Default construct
Value 0
Construct 5
Move assign 5
Destruct 0
Value 5
Destruct 5

令我困惑的是第一次测试的结果。不会调用移动分配运算符,但会执行复制分配。这导致CCD_ 1被破坏两次。当你试图制作一个智能指针时,这并不理想!

我正在使用禁用了优化的Apple Clang进行编译。有人能解释一下我的观察结果吗?此外,如何确保在第一次测试中调用移动分配运算符?

template <typename U>
Foo &operator=(Foo<U> &&other) noexcept;

这不能由CCD_ 2调用。

而是调用Foo& operator=(Foo&&)noexcept

模板方法从来都不是特殊的成员函数。明确默认、删除或实现它们。

最新更新