Lets say you have 2 vectors passed to a function as lvalue references. Later you realize, you can use recursion and pass slices of these vectors using their iterators.
Would it be an appropriate strategy if I go ahead and write some util function to use these vecotrs as 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):
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 tostd::vector<int>(a.begin(), a.end()), i. e. calls the constructor accepting two iterators, which copies all data in between these two iterators, i. e. the whole vector in your case (or sub-ranges of the vector in your more realistic example).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:
const_iterator? Well, we want to acceptconstvectors: