如何解决将本地 std::array 移动到传递的 std::array& 参数
我对将 std::array 操作移动到通过 std::array 容器的引用感到困惑。
我读过评论的地方 这被认为是未定义的行为,还是正确的结果?
还是真的复制元素?
x
结果:
#include <iostream>
#include <array>
#include <algorithm>
using namespace std;
void printElements(string description,array<uint8_t,16>& arr)
{
cout << description << ":\t";
for(auto i:arr)
{
cout << (int)i << " ";
}
cout << "\n";
}
void assignToArr(array<uint8_t,16>& in_out_arr)
{
array<uint8_t,16> arr2;
arr2.fill(4);
move(arr2.begin(),arr2.end(),in_out_arr.begin());
printElements("before arr2 destruction",in_out_arr);
printElements("arr2 before fill(5)",arr2);
arr2.fill(5);
printElements("arr2 after fill(5)",arr2);
}
int main()
{
array<uint8_t,16> arr1;
assignToArr(arr1);
printElements("after arr2 destruction",arr1);
return 0;
}
解决方法
在 C++ 中移动一个普通类型时,它会被复制。
C++ 中的移动操作告诉类型“我们不依赖源数据是之后的内容,随意做一些更有效的事情”。对于普通类型(如 int
),归零或以其他方式更改源没有任何好处。
所以没有。
对于更复杂的类型,比如 std::vector<int>
,移动通常会导致一个空的 std::vector<int>
(并非总是如此!不能保证;只是旧向量将有效地分配给或摧毁)。
std 数组在内部存储它的数据,因此如果类型依次是微不足道的(如果其中的数据是微不足道的,则它本身就是微不足道的)没有有效的移动改进。
Trivial 这里指的是 C++ 标准中使用的术语。
,std::array
将元素直接存储在数组对象中。这就是为什么它的大小必须是编译时常量的原因。当您尝试移动 std::array
时,数组本身不会移动,因为这是不可能的,但其中的元素会移动。移动时对象会发生什么取决于类型。通常,复制类型(int
、double
等)的复制成本较低,对复制对象没有影响。移出更复杂的对象(std::string
和其他容器),并且移出的对象处于“未指定”状态。这意味着它不是未定义的行为,而是未指定的行为。这是一个插图:
#include <array>
#include <iostream>
class Stateful final {
private:
bool m_specifiedState = true;
int m_value = 0;
public:
bool hasSpecified() const noexcept { return m_specifiedState; }
int value() const noexcept { return m_value; }
Stateful(int val) noexcept : m_value(val) {}
Stateful(Stateful const& other) noexcept = default;
Stateful& operator=(Stateful const& other) noexcept = default;
Stateful(Stateful&& other) noexcept
: m_specifiedState(other.m_specifiedState),m_value(other.m_value) {
other.m_specifiedState = false;
}
Stateful& operator=(Stateful&& other) noexcept {
if (this != &other) {
m_specifiedState = other.m_specifiedState;
m_value = other.m_value;
other.m_specifiedState = false;
}
return *this;
}
};
std::ostream& operator<<(std::ostream& os,Stateful const& s) {
if (s.hasSpecified())
os << s.value();
else
os << '?';
return os;
}
template <auto N>
std::ostream& operator<<(std::ostream& os,std::array<Stateful,N> const& arr) {
os << "[ ";
for (auto const& elm : arr) os << elm << ' ';
os << "]";
return os;
}
int main() {
std::array<Stateful,3> arr1{1,2,3};
std::cout << "Arr1 :" << arr1 << '\n';
std::array<Stateful,3> arr2 = std::move(arr1);
std::cout << "Arr1 (moved from):" << arr1 << '\n';
std::cout << "Arr2 (moved to) :" << arr2 << '\n';
}
输出为:
Arr1 :[ 1 2 3 ]
Arr1 (moved from):[ ? ? ? ]
Arr2 (moved to) :[ 1 2 3 ]
如您所见,移动后的数组仍然存在并且仍有 3 个元素,但元素本身已被移动。
,我已经回答了我自己的困惑,before arr2 destruction: 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
arr2: 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
arr2: 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
after arr2 destruction: 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
不存储引用,它直接在堆栈中存储对象。所以它们不能移动,但实际上是复制的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。