移动类的成员作为常量引用参数传递

Moving members of class passed as a const reference argument

本文关键字:常量 引用 参数传递 成员 移动      更新时间:2023-10-16

正在考虑:

template <typename... Args>
ResourceHolder& operator+=(const ResourceInserter<Key, Args...>& inserter) {
if constexpr (sizeof...(Args) == 0) {
insert(std::move(inserter.key),
std::move(inserter.fileName));
} else {
insert(std::move(inserter.key),
std::move(inserter.fileName),
std::move(std::get<Args...>(inserter.tuple)));
}
return *this;
}

你认为这是移动语义的正确用法吗?

ResourceInserterinserter实例作为常量引用传递。

移动 const 对象通常是一个简单的副本(除非你重载Object(const Object&&)(,所以你对std::move的使用似乎毫无用处。

如果ResourceInserter的成员是(非常量(引用, 你的const ResourceInserter&是"误导性的",你的举动实际上会发生。

No.

你正在投射到const Key &&等。Key::Key(const Key&&)通常不能做任何有用的事情,所以你会复制。

您可能希望有一对重载

template <typename... Args>
ResourceHolder& operator+=(const ResourceInserter<Key, Args...>& inserter) {
if constexpr (sizeof...(Args) == 0) {
insert(inserter.key,
inserter.fileName);
} else {
insert(inserter.key,
inserter.fileName,
std::get<Args...>(inserter.tuple));
}
return *this;
}
template <typename... Args>
ResourceHolder& operator+=(ResourceInserter<Key, Args...>&& inserter) {
if constexpr (sizeof...(Args) == 0) {
insert(std::move(inserter.key),
std::move(inserter.fileName));
} else {
insert(std::move(inserter.key),
std::move(inserter.fileName),
std::move(std::get<Args...>(inserter.tuple)));
}
return *this;
}

从右值inserter的成员移动的位置

与它的名字相反,std::move实际上并没有移动任何东西。它只是告诉编译器尝试移动(即,指示对象t可以通过将其转换为右值引用类型[更具体地说,通过生成xvalue表达式]来"移动"(。

但是,您的类没有接受const inserter&&的构造函数,它将使用类的复制构造函数(隐式或显式(,并安全地复制。 没有危险,没有陷阱。如果由于任何原因禁用复制构造函数,则会收到编译错误。

试试这个:

#include <iostream>
struct Test {
Test() { }
Test(const Test& ) { std::cout << "COPY" << std::endl; }
Test(Test&&)       { std::cout << "MOVE" << std::endl; }
};
int main() 
{
const Test t;
Test t2 = std::move(t);
return 0;
}

打印COPY,而不是MOVE