简体   繁体   English

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

[英]C++ pass vector (lvalue to rvalue)

Lets say you have 2 vectors passed to a function as lvalue references . 假设您有2个vectors作为lvalue references传递给函数。 Later you realize, you can use recursion and pass slices of these vectors using their iterators . 后来您意识到,可以使用递归并使用它们的iterators传递这些vectors切片。

Would it be an appropriate strategy if I go ahead and write some util function to use these vecotrs as rvalues ? 如果我继续编写一些util函数以将这些vecotrs用作rvalues那将是一种适当的策略吗? Or I should avoid this in any way? 还是我应该以任何方式避免这种情况?

Simplified pattern: 简化模式:

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() });
}

Realistic example ( LeetCode 105 ): 实际示例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() });
}

You are on the wrong way: {a.begin(), a.end()} is equivalent to std::vector<int>(a.begin(), a.end()) , ie calls the constructor accepting two iterators, which copies all data in between these two iterators, ie the whole vector in your case (or sub-ranges of the vector in your more realistic example). 您使用的是错误的方式: {a.begin(), a.end()}等同于std::vector<int>(a.begin(), a.end()) ,即调用接受两个迭代器,它在这两个迭代器之间复制所有数据,即您所用的整个向量(或者在更实际的示例中为向量的子范围)。

But you don't modify the vectors in any way, so no need for any copies. 但是您不会以任何方式修改向量,因此不需要任何副本。

If you just want to read the original vector, then you can work directly with iterators; 如果您只想读取原始向量,则可以直接使用迭代器。 you can pass these by value, unter the hoods, they are more or less just pointers into the vector's data anyway: 您可以按值传递这些参数,无论如何,它们或多或少只是指向向量数据的指针:

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_iterator Well, we want to accept const vectors: 好吧,我们要接受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...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM