c++ - 是什么导致不调用移动赋值运算符?
问题描述
我正在研究自己的智能指针,但遇到了一些奇怪的问题。未调用移动赋值运算符。所以我写了一个测试类并且能够重现这个问题。不调用移动赋值运算符,但会发生复制赋值(即使没有复制赋值运算符)。
这是我的测试课
#include <utility>
#include <iostream>
struct tag_t {};
constexpr tag_t tag {};
template <typename T>
struct Foo {
Foo() noexcept
: val{} {
std::cout << "Default construct\n";
}
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
让我感到困惑的是第一个测试的输出。不调用移动赋值运算符,但会发生复制赋值。这导致5
被破坏两次。当您尝试制作智能指针时并不理想!
我正在使用禁用优化的 Apple Clang 进行编译。有人可以解释我的观察吗?另外,如何确保在第一次测试中调用了移动赋值运算符?
解决方案
template <typename U>
Foo &operator=(Foo<U> &&other) noexcept;
这不能由 调用={ }
。
而是Foo& operator=(Foo&&)noexcept
被调用。
模板方法从来都不是特殊的成员函数。明确默认、删除或实施它们。
推荐阅读
- angular - 有没有办法将数组参数传递给管道?
- python - 为什么我需要使用 `return` 才能使递归工作?
- python - 如何在不重复行的情况下合并/连接两个数据框,并将具有相同参数的数据框保留在 pandas 的同一行中?
- python - 带十进制的 Python 字典
- wpf - 在画布上跟踪 WPF 元素
- node.js - 捆绑 Quasar/Express/Electron 应用程序进行生产 - Express-server 无法启动
- css - 移除 Ant Design Tag 的额外上边距
- python - 从 imaplib 获取正确解码的邮箱名称
- docker - 如何在 databricksConnectDocker 上运行 Docker 映像而不会出现错误“tiny”
- python - 如何测量时间复杂度