将rvalue引用传递给类构造函数有什么意义?

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

好的

所以我有一个类,MyClass。我想用一个ints的向量来构造这个类。我想把这个向量移动到对象中。这个类是没有模板的。

class Myclass {
     public:
     Myclass (std::vector<int> && in) : vec{in} {};
     Myclass (std::vector<int> & in) : vec{in} {};

    private:
    std::vector<int> vec;
    }

在我的主文件中,我有

std::vector<int> orig (100);
Myclass A {orig};
std::cout << A.size() << '\n';

我希望将 "orig "移入 "A "后为空。在上面的任何一个选项中都不会发生这种情况,即使我做了

    std::vector<int> orig (100);
    Myclass A {std::move(orig)};
    std::cout << A.size() << '\n';  // still prints 100

看来我可以通过

 Myclass (std::vector<int> && in) : vec{std::move(in)} {};   // (1)

 Myclass (std::vector<int> & in) : vec{std::move(in)} {};    // (2)

Myclass (std::vector<int> && in) : vec{std::forward<std::vector<int>(in)} {};    // (3)

我的问题是,为什么(1)的行为和(2)一模一样?

c++ constructor move-semantics rvalue
1个回答
2
投票

关于引用,rvalue和lvalue,需要记住的是它们是l值。 这意味着如果你对一个事物有一个引用,那么这个引用就是一个lvalue,你需要用 std::move 以将其投向一个r值,这样就可以移动它。

之间的真正区别是 Myclass (std::vector<int> && in)Myclass (std::vector<int> & in) 是说,对于第一种情况,你必须使用

Myclass A {std::move(orig)};
// or
Myclass A {std::vector(100)};

而且不能传递一个l值给它,而对于second,你只能使用

Myclass A {orig};

因为它不会让你传递一个r值给它。


同时注意构造函数3是 "不正确的"。 你应该只使用 std::forward 当你有一个转发引用时。 std::vector<int> && in 是一个r值引用,而不是一个转发引用,所以你应该使用 std::move 来代替。 为了正确使用forward,你需要一个模板构造函数,如

template <typename T, std::enable_if_t<
                                       std::is_same<std::decay_t<T>, 
                                       std::vector<int>>, bool> = true>
Myclass (T&& in) : vec{std::forward<T>(in)} {}; 
© www.soinside.com 2019 - 2024. All rights reserved.