C++ 移动作为常量引用参数传递的类的成员
考虑到:C++ 移动作为常量引用参数传递的类的成员,c++,c++11,move-semantics,stdtuple,C++,C++11,Move Semantics,Stdtuple,考虑到: template <typename... Args> ResourceHolder& operator+=(const ResourceInserter<Key, Args...>& inserter) { if constexpr (sizeof...(Args) == 0) { insert(std::move(inserter.key), std::move(inserter.fil
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;
}
你认为这是移动语义的正确用法吗
ResourceInserter的插入器实例作为常量引用传递。移动常量对象通常是一个简单的副本,除非您重载Objectconst对象&&因此您对std::move的使用似乎毫无用处 如果ResourceInserter的成员是非常量引用,
您的const resourceinerter&具有误导性,您的移动实际上会发生。移动const对象通常是一个简单的副本,除非您重载Objectconst对象&因此您对std::move的使用似乎没有用 如果ResourceInserter的成员是非常量引用, 您的const ResourceInserter&具有误导性,您的移动将实际发生。否 您正在强制转换为const Key&&等。Key::keycont 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;
}
从右值插入器的成员移动的位置
您正在强制转换为const Key&&等。Key::keycont 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;
}
如果您从右值插入器的成员移动,而不是从其名称移动,则实际上不会移动任何内容。它只告诉编译器尝试移动,即通过将对象t强制转换为右值引用类型[更具体地说,通过生成]来指示对象t可以从中移动
但是,您的类没有接受常量插入器的构造函数&&,它将使用您的类的隐式或显式,并安全地复制。没有危险,就没有陷阱。如果出于任何原因禁用了复制构造函数,则会出现编译错误
试试这个:
#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;
}
打印副本,而不是移动。与其名称相反,实际上不会移动任何东西。它只告诉编译器尝试移动,即通过将对象t强制转换为右值引用类型[更具体地说,通过生成]来指示对象t可以从中移动
但是,您的类没有接受常量插入器的构造函数&&,它将使用您的类的隐式或显式,并安全地复制。没有危险,就没有陷阱。如果出于任何原因禁用了复制构造函数,则会出现编译错误
试试这个:
#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;
}
打印副本,而不是移动。移动常量对象通常是一个简单的副本。移动常量对象通常是一个简单的副本。