通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
Forwarding Rvalue Of Derived UniquePtr Through Base Class Accepting Method Moves Reference Instead of Copying
似乎将右值引用转发到std::unique_ptr<Derived>
到接受方法,const std::unique_ptr&
基类会导致 std::unique_ptr 被移出。对于数字或非继承类,不会发生这种情况。
最初是在MSVC++ 2019上发现的,但也在各种其他编译器上进行了测试,这些编译器都给出了相同的结果。这种行为是否符合标准?
#include <memory>
#include <cassert>
#include <iostream>
class Base
{};
class Derived : public Base
{};
class NonInheriting
{};
void Corrupter(const std::unique_ptr<Base>&)
{}
void Corrupter(const std::unique_ptr<int>&)
{}
void Corrupter(const std::unique_ptr<NonInheriting>&)
{}
void Usage(std::unique_ptr<Base>&& base)
{
assert(base);
}
void Usage(std::unique_ptr<int>&& base)
{
assert(base);
}
void Usage(std::unique_ptr<NonInheriting>&& base)
{
assert(base);
}
template<class... Args>
void Forwarder(Args&& ... args)
{
Corrupter(std::forward<Args>(args)...);
Usage(std::forward<Args>(args)...);
}
int main()
{
// No assertion
std::cout << "1n";
auto integer = std::make_unique<int>();
Forwarder(std::move(integer));
// No assertion
std::cout << "2n";
auto nonInheriting = std::make_unique<NonInheriting>();
Forwarder(std::move(nonInheriting));
// No assertion
std::cout << "3n";
std::unique_ptr<Base> base = std::make_unique<Derived>();
Forwarder(std::move(base));
// Assertion
std::cout << "4n";
auto derived = std::make_unique<Derived>();
Forwarder(std::move(derived));
return 0;
}
这是预期行为。
对于第 4 种情况,您传递了一个std::unique_ptr<Derived>
,Forwarder
它传递给Corrupter
,后者期望std::unique_ptr<Base>
。std::unique_ptr<Derived>
可以隐式转换为std::unique_ptr<Base>
,然后将参数args
转换为std::unique_ptr<Base>
,指针的所有权也转移到临时std::unique_ptr<Base>
,args
现在一无所有。之后,它被传递给Usage
然后触发断言。
在其他情况下,没有发生转换和所有权转让,那么他们就没有这样的问题。
如果您添加另一个Corrupter
的重载,std::unique_ptr<Derived>
,即消除转换和所有权转让,则没有断言。
住
相关文章:
- 何时在引用或唯一指针上使用移动语义
- 移动赋值运算符;尝试引用已删除的函数.我该如何解决这个问题?
- 设计将引用元素移动到开头的数据结构.C++
- 移动构造函数和右值引用
- 通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
- 使用移动语义:右值引用作为方法参数
- 移动类的成员作为常量引用参数传递
- 可移动但不可复制的对象:按值传递还是按引用传递?
- 垃圾回收正在移动内存中被引用的对象,破坏Unreal4引擎中的引用
- 为什么C++默认情况下不移动构造右值引用?
- 右值引用和局部变量的移动
- 为什么通过引用返回向量比通过移动返回要快得多?
- C++模板成员初始化:用右值移动构造,但用左值移动引用
- 通过引用捕获与移动,lambdas
- 在不中断引用的情况下移动静态库的 *.pdb 文件 - LNK4099
- C 移动语义:将唯一_ptr引用的矩阵附加到向量
- 包含仅移动类型的类的构造函数应通过引用还是通过右值引用接收仅移动类型?
- 被引用的移动对象
- 我可以将数组每次移动引用传递给 std::thread 吗?
- 这是使用移动引用和unique_ptr的正确方式吗