C++ 传递向量(左值到右值)

Posted

技术标签:

【中文标题】C++ 传递向量(左值到右值)【英文标题】:C++ pass vector (lvalue to rvalue) 【发布时间】:2019-07-29 07:58:03 【问题描述】:

假设您有 2 个vectors 作为lvalue references 传递给函数。后来你意识到,你可以使用递归并使用它们的iterators 传递这些vectors 的切片。 如果我继续编写一些 util 函数以将这些 vecotrs 用作 rvalues ,这是否是一个合适的策略?或者我应该以任何方式避免这种情况?

简化模式:

Node* util(vector<int>&& a, vector<int>&& b) 
    Node* root = new Node(a[0]);

    root->left = util( a.begin(), a.end() ,  b.begin(), b.end() );
    root->right = util( a.begin(), a.end() ,  b.begin(), b.end() );

    return root;


Node* main(vector<int>& a, vector<int>& b) 
    return util( a.begin(), a.end() ,  b.begin(), b.end() );

现实例子 (LeetCode 105):

TreeNode* util(vector<int>&& preorder, vector<int>&& inorder) 
    if (!preorder.empty()) 
        TreeNode* root = new TreeNode(preorder[0]);

        auto r = find(inorder.begin(), inorder.end(), preorder[0]);

        root->left = util(
         preorder.begin() + 1, preorder.begin() + 1 + distance(inorder.begin(), r) ,
         inorder.begin(), r );
        root->right = util(
         preorder.begin() + 1 + distance(inorder.begin(), r), preorder.end() ,
         r + 1, inorder.end() );

        return root;
    
    return nullptr;


TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    return util( preorder.begin(), preorder.end() , 
                 inorder.begin(), inorder.end() );

【问题讨论】:

我不明白你为什么需要右值引用(你想移动任何数据吗???),普通的引用也应该没问题。由于您似乎没有修改输入向量,因此 const 引用将是合适的。 这不是为每个参数构造一个全新的向量吗?右值不会阻止这种情况的发生 我无法通过普通引用传递向量迭代器。此语法 root-&gt;left = util( a.begin(), a.end() , b.begin(), b.end() ); 不起作用 @Tharwen 也正要修改我之前在这个方向上的评论......是的,我们正在创建副本而不修改它们。所以:我之前的评论中的 const 引用,只是递归调用 util(preorder, inorder); 应该是绝对没问题的。 @user2376997 可以按值传递迭代器;在幕后,你或多或少只是将指针传递给数据......提供迭代器作为你的 util 函数的参数,你可以这样做。 a.begin(), a.end() 等价于 std::vector&lt;int&gt;(a.begin(), a.end()),即。 e.调用接受两个迭代器的构造函数,它复制这两个迭代器之间的所有数据,即。 e.你的情况下的整个向量。 【参考方案1】:

你走错路了:a.begin(), a.end() 等价于std::vector&lt;int&gt;(a.begin(), a.end()),即。 e.调用接受两个迭代器的构造函数,它复制这两个迭代器之间的所有数据,即。 e.您的案例中的整个向量(或您更实际示例中的向量的子范围)。

但您不会以任何方式修改向量,因此不需要任何副本。

如果你只想读取原始向量,那么你可以直接使用迭代器;您可以按值传递这些值,在幕后,它们或多或少只是指向向量数据的指针:

TreeNode* util
(
    vector<int>::const_iterator preorderBegin, vector<int>::const_iterator preorderEnd,
    vector<int>::const_iterator inorderBegin, vector<int>::const_iterator inorderEnd
)

    // ...
    ++preorderBegin; // if we do so before the call, we have just one addition; compiler
                     // might optimize to the same code, but we don't rely on it this way
    util(preorderBegin, preorderBegin + distance(), inorderBegin, r);
    // ...

const_iterator?好吧,我们要接受const 向量:

TreeNode* buildTree(vector<int> const& preorder, vector<int> const& inorder)
//                                ^                            ^
// you don't modify the vectors, so accept them as constant

    return util(preorder.begin(), preorder.end(), inorder.begin(), inorder.end());
    // note the dropped braces...

【讨论】:

以上是关于C++ 传递向量(左值到右值)的主要内容,如果未能解决你的问题,请参考以下文章

无序映射的左值到右值转换

在 C++ 11 中将非 const 左值引用绑定到右值是不是有效?(修改)

右值到左值转换 Visual Studio

左值绑定到右值引用

左值绑定到右值引用

error C2662 无法将左值绑定到右值 —— 变量永远是左值,即使它的类型为右值引用