通过右值引用将 std::unique_ptr 传递给构造函数

问题描述 投票:0回答:2

考虑下面的两个构造函数:

// Passing data_ by r-value reference:
class A
{
public:

    A(std::unique_ptr<int>&& data_);

    // ...
};

// Passing data_ by value:
class B
{
public:

    B(std::unique_ptr<int> data_);

    // ...
};

我一直在问自己哪个构造函数更适合拥有

data_
。这个nice answer似乎表明通过r值参考的方法可能不是最好的方法。来自这个答案的推荐部分:

(D) 通过 r 值引用: 如果一个函数可能会或可能不会声明所有权(取决于内部代码路径),则通过

&&
获取它。 但我强烈建议尽可能不要这样做。

我曾尝试使用右值方法和按值方法编写一个单元测试来显示差异,但失败了。在所有情况下,两个构造函数的工作方式相同,并且数据始终被移动。答案的作者似乎表明,根据内部代码路径,可以忽略此移动。进一步引用答案:

问题是没有。不保证被感动 从。它可能已被移动,但您只有通过查看才能知道 在源代码。你不能仅仅从函数签名中分辨出来。

任何人都可以给我一个可以忽略移动的场景的例子吗?

c++ c++20 move unique-ptr
2个回答
2
投票

例如在下面的代码中,两个类都没有使用传入的指针:

#include <memory>
#include <iostream>

class A
{
public:

    A(std::unique_ptr<int>&& data_) {}
};

// Passing data_ by value:
class B
{
public:

    B(std::unique_ptr<int> data_) {}
};

int main()
{
    auto a = std::make_unique<int>(5);
    A{std::move(a)};
    auto b = std::make_unique<int>(5);
    B{std::move(b)};
    std::cout << (a == nullptr) << "\n";
    std::cout << (b == nullptr) << "\n";
}

https://godbolt.org/z/dbbcKbs79

A
中,指针通过右值引用传递给
data_
,引用未被使用,因此原始
a
指针未被修改。

B
中指针被移动到临时值
data_
中,指针没有被使用但是原来的
b
指针仍然被重置为null。


0
投票

你在这里表现得还不够。通常,我们在转让所有权时传递价值

class B
{
    std::unique_ptr<int> data;

public:
    B(std::unique_ptr<int> data)
      : data{std::move(data)}
    {}
};

根本不要在不打算传输的地方使用

std::unique_ptr
(使用原始指针,或者如果保证非空则可能是引用)。如果所有权可能会也可能不会被转移,这取决于编译时未知的东西,那么这是通过右值引用传递的唯一(而且非常罕见)用途。在我的整个职业生涯中,我从来不需要这样做。

© www.soinside.com 2019 - 2024. All rights reserved.