Here is the code, I am very confused. swap function is usually used to exchange the value of two parameters, like a.swap(b) or swap(a, b). What is the meaning of swap here?
std::vector<int> search_indices;
std::vector<float> distances;
int keypointNum = 0;
do
{
keypointNum++;
std::vector<int>().swap(search_indices);
std::vector<float>().swap(distances);
int id;
iterUnseg = unVisitedPtId.begin();
id = *iterUnseg;
indices->indices.push_back(features[id].ptId);
unVisitedPtId.erase(id);
tree.radiusSearch(features[id].pt, _curvature_non_max_radius, search_indices, distances);
for (int i = 0; i < search_indices.size(); ++i)
{
unVisitedPtId.erase(search_indices[i]);
}
} while (!unVisitedPtId.empty());
I have looked for how swap function works, no related explanations.
Given std::vector<int> v; definition, std::vector<int>().swap(v); clears vector v and disposes of the memory it reserved (so that v.capacity() returns 0). Starting from C++11, an arguably better way to write it is:
v.clear();
v.shrink_to_fit();
It is a trick to clear a vector and free all the allocated memory for its elements.
In these statements
std::vector<int>().swap(search_indices);
std::vector<float>().swap(distances);
there are used empty temporary created vectors, std::vector<int>() and std::vector<float>(), that are swapped with the vectors search_indices and distances.
After the calls of the member function swap the both vectors search_indices and distances become empty. In turn the temporary vectors that after the swapping contain the elements of the above two vectors will be destroyed.
This trick is used because if you will just write
search_indices.clear();
distances.clear();
the allocated memory can be preserved. That is the member function capacity can return a non-zero value.
Here is a demonstration program.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = { 1, 2, 3, 4, 5 };
std::cout << "v.size() = " << v.size() << '\n';
std::cout << "v.capacity() = " << v.capacity() << '\n';
std::cout << '\n';
v.clear();
std::cout << "v.size() = " << v.size() << '\n';
std::cout << "v.capacity() = " << v.capacity() << '\n';
std::cout << '\n';
std::vector<int>().swap( v );
std::cout << "v.size() = " << v.size() << '\n';
std::cout << "v.capacity() = " << v.capacity() << '\n';
}
The program output is
v.size() = 5
v.capacity() = 5
v.size() = 0
v.capacity() = 5
v.size() = 0
v.capacity() = 0
As you can see after calling the member function swap with the temporary empty vector the capacity of the vector v becomes equal tp 0.
To get the same effect using the method clear you should after calling it also to call the method shrink_to_fit(). For example
v.clear();
v.shrink_to_fit();
It seems that this is a strategy to free up memory. I wrote a test code here:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<int> test(9, 0);
std::cout <<test.size() << std::endl;
std::vector<int>().swap(test);
std::cout <<test.size() << std::endl;
cout<<"Hello World";
return 0;
}
The output is:
9
0
Hello World
Related
I'm currently trying to re-implement the vector container. I just read on this website that vector<T>().swap(x);, where x is a vector previously declared, could be used to clear and reallocate the x vector to 0.
I realized with this example that I'm not familiar with the use of a constructor (or what I think is a constructor).
#include <iostream>
#include <string>
#include <vector>
typedef std::string T;
void display(const std::vector<T>& input) {
std::cout << "------START------" << std::endl;
for (int i = 0; i < input.size(); i++)
std::cout << input[i] << std::endl;
std::cout << "------END-------" << std::endl;
std::cout << "input size: " << input.size() << std::endl;
std::cout << "input capacity: " <<input.capacity() << std::endl;
}
int main() {
std::vector<T> src(1, "Matthieu0");
std::vector<T> empty;
src.push_back("Guillaume1");
src.push_back("Paul2");
src.push_back("Julien3");
std::vector<T> tmp(src);
std::cout << "------swap1------" << std::endl;
display(empty);
empty.swap(tmp);
display(empty);
std::cout << "------swap2------" << std::endl;
display(src);
std::vector<T>().swap(src);
display(src);
return 0;
}
So, I have no problem understanding swap1 behavior, crystal clear. But I don't understand what is happening under the hood with swap2 and how I could implement it.
But I don't understand what is happening under the hood with swap2
When you wrote
//-vvvvvvvvvvvvvvvv------------->a temporary std::vector
std::vector<T>().swap(src); //this calls swap on the temporary(unnamed) std::vector
In the above statement you're calling std::vector::swap on the temporary(unnamed) std::vector created from the expression std::vector<T>().
This is similar to the swap1 that you did with the exception that in swap1 you were calling std::vector::swap on a named object empty but here you're calling it on the temporary object.
Many developers want to release memory occupied by a vector after std::vector::resize(0).
It can be done since C++11 by calling std::vector::shrink_to_fit(). There is no such method until C++11, in C++98, and developers use such a trick:
Create an empty vector.
Swap contents of vectors.
Destroy the vector created on the step 1.
For performing the step 3 as much earlier as possible, the limited scope block { ... } is used.
std::vector<int> v(10);
std::cout << v.size(); << std::end; // prints 10
{
std::vector<int> tmp;
std::cout << tmp.size(); << std::end; // prints 0
v.swap(tmp);
std::cout << tmp.size(); << std::end; // prints 10
}
std::cout << v.size(); << std::end; // prints 0
It can be shorter if an unnamed temporary vector generated by a compiler is used. The life time of an unnamed temporary variable is well known:
std::vector<int> v(10);
std::cout << v.size(); << std::end; // prints 10
v.swap(std::vector<int>());
std::cout << v.size(); << std::end; // prints 0
std::vector<int> v(10);
std::cout << v.size(); << std::end; // prints 10
std::vector<int>().swap(v);
std::cout << v.size(); << std::end; // prints 0
It can be still used since C++11 for making
v.resize(0);
v.shrink_to_fit();
shorter and to guarantee freeing memory:
v.swap({});
I have the following test code that's runnable under clang.
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> vs{1, 2, 4, 5};
std::vector<std::reference_wrapper<int>> vs1;
for (int i : vs) {
std::cout << "loop: " << i << std::endl;
vs1.emplace_back(i);
}
for (auto p : vs1) {
std::cout << p << std::endl;
}
return 0;
}
You can plug that into https://rextester.com/l/cpp_online_compiler_clang (or locally). The result is:
loop: 1
loop: 2
loop: 4
loop: 5
5
5
5
5
I'd expect 1,2,4,5, not 5 all the way.
The code won't work on non-clang. Where's the problem?
i is a local variable inside its declaring for loop. It is a copy of each int in the vs vector. You are thus (via the emplace_back() call) creating reference_wrapper objects that refer to a local variable, keeping the references alive after the lifetime of the referred-to variable (i) has ended. This is undefined behavior.
The fix is to make i be a reference to each int, not a copy, that way the reference_wrappers refer to the ints in vs as expected:
for (int& i : vs)
First, you forgot <functional> header.
Second, reference_wrapper<int> stores reference to an int. Not its value. So in this loop:
for (int i : vs) {
std::cout << "loop: " << i << std::endl;
vs1.emplace_back(i);
}
You are changing value of i but not its place in memory. It is always the same variable. That's why it prints the last value stored in that variable, which is 5.
You may imagine this range- based for loop
for (int i : vs) {
std::cout << "loop: " << i << std::endl;
vs1.emplace_back(i);
}
the following way
for ( auto first = vs.begin(); first != vs.end(); ++first )
{
int i = *first;
vs1.emplace_back(i);
}
that is within the loop you are dealing with the local variable i that will not be alive after exiting the loop.
You need to use a reference to elements of the vector like
for (int &i : vs) {
std::cout << "loop: " << i << std::endl;
vs1.emplace_back(i);
}
Consider the following code:
#include <vector>
#include <iostream>
void monitor_vector(std::vector<int> myV)
{
std::vector<int>::iterator it = myV.begin();
std::cout << "Vector size: " << myV.size() << std::endl;
while (*it)
{
std::cout << "Element " << it-myV.begin() << ": " << *it << std::endl;
it++;
}
}
int main()
{
std::vector<int> myVector(4,1);
monitor_vector(myVector);
return 0;
}
Basically, I create a std::vector<int> that has 4 elements, and assign each element 1. When I execute this code, all is well. The output shows each element.
However, when I execute it with this line
std::vector<int> myVector(4,1);
replaced by this line:
std::vector<int> myVector(4,0);
I can't see any output. The output is:
yilmazali#yilmazali:~/cpp_practice$ g++ -o la vector_practice.cpp
yilmazali#yilmazali:~/cpp_practice$ ./la
Vector size: 4
yilmazali#yilmazali:~/cpp_practice$
Why does it ignore the elements with default integer value? Still, they are there as the member of std::vector.
Thanks for your time,
Ali
You iterate while (*it).
If you fill your vector with zeros, *it == 0 and therefore if (*it) is like if (false): the loop body is never executed.
Instead, loop while it != myV.end()
I'm trying to figure out how the memory management for std::vector works when you remove elements. It is my understanding that once memory was allocated for the vector, no pop_back\erase action would reduce the capacity of the vector, and the only way to do so is using shrink_to_fit which was introduced in C++ 11. Please correct me if I'm wrong.
You are correct, mostly.
There are only a few ways to reduce a std::vector's capacity…
Move Assignment
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v1(10);
std::vector<int> v2(20);
std::cout << "v2.capacity() = " << v2.capacity() << '\n';
std::cout << "Move assign v2 with less capacity\n";
v2 = std::move(v1);
std::cout << "v2.capacity() = " << v2.capacity() << '\n';
}
which should output:
v2.capacity() = 20
Move assign v2 with less capacity
v2.capacity() = 10
If the allocator involved is set a certain way, diminished capacity is not assured. But in the common case as shown above, capacity will shrink. If you really want to know about the nitty gritty details of how capacity might not shrink during move assignment, ask another question, and I can dig into that in detail.
shrink_to_fit
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v(20);
std::cout << "v.capacity() = " << v.capacity() << '\n';
std::cout << "erasing...\n";
v.erase(v.begin() + v.size()/2, v.end());
std::cout << "v.capacity() = " << v.capacity() << '\n';
std::cout << "shrink_to_fit...\n";
v.shrink_to_fit();
std::cout << "v.capacity() = " << v.capacity() << '\n';
}
which will probably output:
v.capacity() = 20
erasing...
v.capacity() = 20
shrink_to_fit...
v.capacity() = 10
But it is allowed to output:
v.capacity() = 20
erasing...
v.capacity() = 20
shrink_to_fit...
v.capacity() = 20
swap
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v(20);
std::vector<int> v2(10);
std::cout << "v.capacity() = " << v.capacity() << '\n';
std::cout << "swap...\n";
swap(v, v2);
std::cout << "v.capacity() = " << v.capacity() << '\n';
}
which should output:
v.capacity() = 20
swap...
v.capacity() = 10
I know of no other ways to shrink the capacity of a vector (besides obviously equivalent constructs such as v.swap(v2)).
A good rule of thumb is that the capacity of a vector never shrinks unless:
It transfers resources with another vector (e.g. move assignment or swap).
shrink_to_fit is called.
Oh, and I nearly forgot a third possibility: any time you move from a vector, the moved-from vector might have a diminished capacity (or it might not). It is unspecified, so you can't count on it. In general moved-from values should be variables where you don't care what their current state is. You will subsequently destruct them or assign them a new known state (assignment doesn't have to be via the assignment operator; could be clear() followed by push_back() for example).
can someone please explain to me in detail why the following code for vectorY will do the assignment but the size of VecY is zero? Also, the begin and end iterators are stuck at the first node. It seems that reserve only works with push back and that you need to construct the vector with the size if you want the iterators for the vectors and the size to work as expected. I am assuming that push_back is doing some type of allocation that the straight assignment is not in this case? I am looking for details explaining this so I can make sure I understand what is happening with a reserve and push_back versus constructing with a size element and then doing assignment as in VecX example.
#include <iostream>
#include <vector>
int main ( int argc, char *argv[])
{
std::vector<int> vecX(2);
vecX[0] = 1;
vecX[1] = 2;
std::cout << " VecX0 Item: " << vecX[0] << std::endl;
std::cout << " VecX1 Item: " << vecX[1] << std::endl;
std::cout << " VectorX Size: " << vecX.size() << std::endl;
std::vector<int> vecY;
vecY.reserve(2);
vecY[0] = 1;
vecY[1] = 2;
std::cout << " VecY0 Item: " << vecY[0] << std::endl;
std::cout << " VecY1 Item: " << vecY[1] << std::endl;
std::cout << " VectorY Size: " << vecY.size() << std::endl;
}
Output
VecX0 Item: 1
VecX1 Item: 2
VectorX Size: 2
VecY0 Item: 1
VecY1 Item: 2
VectorY Size: 0
std::vector<int> vecY;
vecY.reserve(2);
vecY[0] = 1;
vecY[1] = 2;
This code is wrong and evokes Undefined Behavior1. When you reserve a vector, you set the capacity, not the size.
You need to either push_back, or construct the vector as you did in example 1.
"Undefined Behavior" : This invokes Undefined Behavior because of the out-of-range call to operator[] If you call vector::operator[n] where n > vec.size(), the behavior is Undefined.
If you don't want use push_back nor construct, consider using the resize method