I'm a C++ beginner and I'm trying to write a method which will take two vectors and add together their contents.
For example,
v1{1,2,3}+v2{2,4,6} should yield v3{3,6,9}.
Here's what my code looks like right now:
Vec Vec::operator+(const Vec& original){
if(mySize != original.mySize){
throw invalid_argument ("No!");
}
Item* sumVector = new Item(mySize);
for(unsigned i=0; i<mySize; i++){
sumVector[i] = myArray[i] + original.myArray[i];
}
return * sumVector;
}
However, this isn't working because my assertion v3.getItem(0) == 3 is failing. I'm sure you already know this if you're answering this question but Vec is the name of one of my classes in this and Item is a typedef double.
As juanchopanza mentioned in the comments, sumVector is a pointer. Unfortunately for you, operator[] is defined for pointers, which may have given a confusing compile error for beginners.
For a solution that best retains the erroneous intent of the original code, this:
sumVector[i] = myArray[i] + original.myArray[i];
needs to be this:
(*sumVector)[i] = myArray[i] + original.myArray[i];
This way, you de-reference the pointer first, then access operator[] for the vector class. This is really bad though, and probably not even a solution.
You must understand what your code is doing. You are allocating a new array of Items on the heap, and then returning a copy of a Vec using the *Item, which is equivalent to Item[0], as the Vec's constructor. Not only are you constructor a Vec with a single double input (without seeing your class declarations I can't know if this is a valid thing, but it probably isn't), but this heap allocation of Items will never have a corresponding free since you have lost the only reference to it when you leave the function scope. You will never be able to free the memory, which means it is a memory leak.
The correct intent (I assume) is to create a local vector on the stack with computations, and then return it. This means changing two lines:
Item* sumVector = new Item(mySize)
return * sumVector;
to
Vec sumVector(mySize); //now this is actually a vector
return sumVector;
Note that vector types usually just hold a pointer in their class type, in addition to some metadata. This pointer value is allocated on the stack, and the pointer itself points to heap memory which the vector manages.
Change this statement
Item* sumVector = new Item(mySize);
to
Item* sumVector = new Item[mySize];
And instead of
return * sumVector;
there shall be
return sumVector;
provided that class Vec has a constructor with parameter of type Item *
However in any case there is a problem with the constructor because even it has a parameter of type Item * it does not know how many elements were allocated.
So you have to create an object of type Vec inside the body of the operator.
Also it would be better to declare the operator as
Vec Vec::operator+(const Vec& original) const;
Related
I'm currently refactoring and change existing code to C++11 and I wonder if have memory leak. My code has a struct with a std::vector in it as well as a method to shrink() this vector down to its negative elements.
struct mystruct_t {
int other_stuff;
std::vector <int> loc;
// Adds elements to loc vector
void add(int pos){
loc.push_back(pos);
}
// Shrink the list
void shrink () {
std::vector<int> tmp;
for (unsigned int i = 0; i < loc.size(); ++i) {
if (loc[i] < 0) tmp.push_back (loc[i]);
}
loc = tmp;
std::vector<int>(loc).swap (loc);
}
mystruct_t(): otherstuff(0) {};
};
In another function I create a new instance of this struct like this:
mystruct_t c = new mystruct_t;
c->add(2);
c->add(3);
...
And later I call the shrink() method of this struct.
c->shrink()
Now I'm not sure what's happening with the "old" loc vector after the shrink function?
Will it get destroyed automatically or do I have to destroyed by hand? And if the later, how would I do that?
I also tried to change shrink() to more C++11 style by change it to:
void shrink (){
std::vector<int> tmp;
for (auto &currLoc : loc) {
if (currLoc < 0) tmp.push_back (currLoc);
}
loc = std::move(tmp);
}
But the question remains the same what is happening to the "old" loc vector additionally this seems to increase the memory usage. I'm new to C++11 and not sure if I totally misunderstand the concept?
Now I'm not sure what's happening with the "old" loc vector after the shrink function?
There is no "old" loc vector. Through the lifetime of a mystruct_t object, it has exactly one member vector loc. You never get a new member or throw away an old one.
When you copy assign to the member (loc = tmp;), the buffer - cotained within the vector - is renewed. The vector owns the buffer, and the vector takes care that it is destroyed properly. Same applies when you move assign in the c++11 version.
Will it get destroyed automatically
If you refer to the memory allocated by the vector, then yes.
or do I have to destroyed by hand?
You have to destroy by hand only whatever you created by hand. You didn't call new, so you don't call delete.
additionally this seems to increase the memory usage.
Your c++11 version lacks the "shrink to fit" part of the original (std::vector<int>(loc).swap (loc);). In c++11 you can do:
loc = std::move(tmp);
loc.shrink_to_fit();
In the pre c++11 version, can get rid of the copy assignment and simply construct the temporary from tmp, and swap it with loc:
std::vector<int> tmp;
// copy the objects you want
std::vector<int>(tmp).swap(loc);
Operation std::move just casting values, so there is no additional memory usage.
When you use std::move compiler will remove head address of first object, and just reassign memory to second object. So it's very fast operation, etc just changing the head of data.
Suppose that T contains an array whose size may vary depending on initialization. I'm passing a pointer to the vector to avoid copying all the data, and initialize as follows:
for(int i=10; i < 100; i++)
std::vector.push_back(new T(i));
On exiting, one deletes the element's of the vector. Is there a risk of memory loss if the data contained in T is also a pointer, even if there are good destructors? Eg
template<class M> class T{
M * Array;
public:
T(int i) : Array(new M[i]){ }
~T(){ delete Array;}
};
There are two major problems with your class T:
You use delete rather than delete [] to delete the array, giving undefined behaviour
You don't implement (or delete) the copy constructor and copy-assignment operator (per the Rule of Three), so there's a danger of two objects both trying to delete the same array.
Both of these can be solved easily by using std::vector rather than writing your own version of it.
Finally, unless you have a good reason (such as polymorphism) to store pointers, use std::vector<T> so that you don't need to manually delete the elements. It's easy to forget to do this when removing an element or leaving the vector's scope, especially when an exception is thrown. (If you do need pointers, consider unique_ptr to delete the objects automatically).
The answer is: don't.
Either use
std::vector<std::vector<M>> v;
v.emplace_back(std::vector<M>(42)); // vector of 42 elements
or (yuck)
std::vector<std::unique_ptr<M[]>> v;
// C++11
std::unique_ptr<M[]> temp = new M[42]; // array of 42 elements
v.emplace_back(temp);
// C++14 or with handrolled make_unique
v.emplace_back(std::make_unique<M[]>(42);
which both do everything for you with minimal overhead (especially the last one).
Note that calling emplace_back with a new argument is not quite as exception-safe as you would want, even when the resulting element will be a smart pointer. To make it so, you need to use std::make_unique, which is in C++14. Various implementations exist, and it needs nothing special. It was just omitted from C++11, and will be added to C++14.
I want to know if there is a way to keep track of addresses of elements in a vector.
I like to use vector of solid elements like std::vector<MyObject> vec because:
std::vector do all the allocation / deallocation stuff for me
it also ensures me that my elements are stored in contiguous memory
I can get benefits of all code that work with vectors (e.g. <algorithm>)
This is exactly what I want. The problem arises when I want to store the address / reference of elements of my vector in other objects. In fact, the problem really arises when std::vector need to reallocate memory.
I tried to find alternatives to my problem:
Use vector of pointers / smart pointers : No, the pointers will be allocated contiguously but not the elements
Use vector of pointers / smart pointers and write my own operator new/new[] for MyObject : Humm, that seems better but no. By using a vector to allocate my elements I can say : "those particular set (I do not refer here to std::set) of elements must be allocated contiguously, not all". In fact I may want to have other set of elements that should be allocated contiguously because of the way I want to use them and using a vector to do that is exactly what (I think) I need. Thats also implies that I'm doing the job I want the vector to do.
Why not using boost multi-index? : In some ways that will do what I want because I want to store pointers/smartpointers of my vector elements in other containers. But no again because I really want to store reference/pointer/smartpointer of my vector's elements inside other objects, not just other containers.
What I would loved to have is a vector that can give me a pointer object that will allways point the the address of the desired element and I will use it like that :
std::vector<MyObject> vec;
// insert some elements
...
// get a pointer object by index or by using an iterator
// does something like that exist?
std::vector<MyObject>::pointer ptr = vec.get_pointer_at(5);
// do what I want on the vector except removing the element
...
// use my pointer whatever reallocations occurred or not
ptr->doSomething();
That sounds like an iterator that will never be invalidated except the fact I don't need/want to perform arithmetic on it (+x, -x, ++, --).
So, can someone leads me to the way to achieve what I want or explain me why/where I'm wrong wanting to do this? Please accept my apologize for my lack of knowledge in STL if there is a well known solution that I missed / or if this question has already be answered.
Edit:
I think that if I have to code such kind of pointer, that means that I'm wanting something useless or I'm wrong somewhere (unless someone should have already wrote a template for that) . So I'm more looking to a validated C++ idiom to get rid of this problem.
Although std::vector does not give you such pointer, there is no reason why you cannot make one yourself. All it takes is a class that keeps a reference to the std::vector object and the index, and overloads the prefix operator * and the infix operator -> (you need four overloads - const and non-const for each operator).
You would use this pointer like this:
std::vector<int> vect = {2, 4, 6, 8, 10, 12, 14, 16};
vect_ptr<int> ptr(vect, 5); // <<== You need to implement this
*ptr = 123;
cout << *ptr << endl;
The implementation of these overloads would grab the std::vector's begin() iterator, and return the result of calling vect.at(index). This would look like a pointer from the outside, but the object to which it points would change as the content of the std::vector gets resized.
As far as I know, there is nothing in the standard library nor in Boost to address your problem. A solution would be to implement your own kind of element pointer:
template<typename T>
class vector_element
{
public:
vector_element( std::vector<T>& v, std::size_t i )
: m_container( v ), m_element_index(i)
{ }
T& operator*() { return m_container[m_element_index]; }
T* operator->() { return &m_container[m_element_index]; }
private:
std::vector<T>& m_container;
std::size_t m_element_index;
};
I am trying to include a vector in my struct.
Here is my struct:
struct Region
{
bool hasPoly;
long size1;
long size2;
long size3;
long size4;
long size5;
long size6;
//Mesh* meshRef; // the mesh with the polygons for this region
long meshRef;
std::vector<int> PVS;
} typedef Region;
Is the vector in this declaration valid or would it make more sense to do a pointer to a vector. In the case of a pointer to a vector, do I need to allocate a new vector. How would I accomplish this?
Thanks!
Edit: The problem is that it ends up causing an error that points to xmemory.h, a file included with the MSVC++ platform.
void construct(pointer _Ptr, _Ty&& _Val)
{ // construct object at _Ptr with value _Val
::new ((void _FARQ *)_Ptr) _Ty(_STD forward<_Ty>(_Val)); // this is the line
}
Interestingly, it does not happen if I allocate it outside of the struct and simply in the function I use. Any ideas?
You can write it like this without the typedef:
struct Region
{
bool hasPoly;
long size1;
long size2;
long size3;
long size4;
long size5;
long size6;
long meshRef;
std::vector<int> PVS;
}; // no typedef required
To answer your questions:
Is the vector in this declaration valid
Yes, it is.
or would it make more sense to do a pointer to a vector.
No, probably not. If you did then you would have to implement copy constructor, assignment operator and destructor for the copy behavior. You would end up with the same but it would be extra work and potentially introduce bugs.
In the case of a pointer to a vector, do I need to allocate a new vector. How would I accomplish this?
You would need to implement the copy constructor, the copy assignment operator and the destructor:
// Copy constructor
Region(const Region & rhs) :
hasPoly(rhs.hasPoly),
// ... copy other members just like hasPoly above, except for PVS below:
PVS(new std::vector<int>(*rhs.PVS))
{
}
// Copy assignment operator
Region & operator=(const Region & rhs)
{
if (this != &rhs)
{
hasPoly = rhs.hasPoly;
// ... copy all fields like hasPoly above, except for PVS below:
delete PVS;
PVS = new std::vector<int>(*rhs.PVS);
}
return *this;
}
// Destructor
Region::~Region()
{
delete PVS;
}
Bottom line: your code is fine. You don't need to change it.
EDIT: Fix assignment operator: check for comparison against this and return *this.
It makes complete sense to do that and you don't need new in any respect, unless you actually want to alias a separate vector. In addition, you don't need any typedef stuff going on here.
It depends on how you use it.
If you want to copy the vector and data when copying the Region struct, then leave it as a non-pointer.
If you don't want it copied over, then you will want some sort of pointer to a vector.
If you use a pointer to a vector, you should be very careful about allocation/deallocation exception safety. If you can't scope your allocation in an exception safe way, then you'll leave a potential for memory leaks.
A couple options are:
Make sure that the code that allocates the vector (and uses the Region) also deallocates the vector, and is itself exception safe. This would require the Region to only exist inside that code's scope.
You could do this by simply allocating the vector on the stack, and pass that to the pointer in the Region. Then make sure you never return a Region object above that stack frame.
You could also use some sort of smart pointer -> vector in your Region.
The vector is fine. Be aware that if you copy this struct, then the vector will be copied with it. So in code with particular performance constraints, treat this struct the same way that you'd treat any other expensive-to-copy type.
In production code, some people would prefer you to use the class keyword rather than the struct keyword to define this class, since the vector member makes it non-POD. If you're the author of your own style guide there's nothing to worry about.
The typedef is wrong, though, just write struct Region { stuff };
I have a vector of myObjects in global scope.
I have a method which uses a std::vector<myObject>::const_iterator to traverse the vector, and doing some comparisons to find a specific element.
Once I have found the required element, I want to be able to return a pointer to it (the vector exists in global scope).
If I return &iterator, am I returning the address of the iterator or the address of what the iterator is pointing to?
Do I need to cast the const_iterator back to a myObject, then return the address of that?
Return the address of the thing pointed to by the iterator:
&(*iterator)
Edit: To clear up some confusion:
vector <int> vec; // a global vector of ints
void f() {
vec.push_back( 1 ); // add to the global vector
vector <int>::iterator it = vec.begin();
* it = 2; // change what was 1 to 2
int * p = &(*it); // get pointer to first element
* p = 3; // change what was 2 to 3
}
No need for vectors of pointers or dynamic allocation.
Returning &iterator will return the address of the iterator. If you want to return a way of referring to the element return the iterator itself.
Beware that you do not need the vector to be a global in order to return the iterator/pointer, but that operations in the vector can invalidate the iterator. Adding elements to the vector, for example, can move the vector elements to a different position if the new size() is greater than the reserved memory. Deletion of an element before the given item from the vector will make the iterator refer to a different element.
In both cases, depending on the STL implementation it can be hard to debug with just random errors happening each so often.
EDIT after comment: 'yes, I didn't want to return the iterator a) because its const, and b) surely it is only a local, temporary iterator? – Krakkos'
Iterators are not more or less local or temporary than any other variable and they are copyable. You can return it and the compiler will make the copy for you as it will with the pointer.
Now with the const-ness. If the caller wants to perform modifications through the returned element (whether pointer or iterator) then you should use a non-const iterator. (Just remove the 'const_' from the definition of the iterator).
You can use the data function of the vector:
Returns a pointer to the first element in the vector.
If don't want the pointer to the first element, but by index, then you can try, for example:
//the index to the element that you want to receive its pointer:
int i = n; //(n is whatever integer you want)
std::vector<myObject> vec;
myObject* ptr_to_first = vec.data();
//or
std::vector<myObject>* vec;
myObject* ptr_to_first = vec->data();
//then
myObject element = ptr_to_first[i]; //element at index i
myObject* ptr_to_element = &element;
It is not a good idea to return iterators. Iterators become invalid when modifications to the vector (inversion\deletion ) happens. Also, the iterator is a local object created on stack and hence returning the address of the same is not at all safe. I'd suggest you to work with myObject rather than vector iterators.
EDIT:
If the object is lightweight then its better you return the object itself. Otheriwise return pointers to myObject stored in the vector.
As long as your vector remains in global scope you can return:
&(*iterator)
I'll caution you that this is pretty dangerous in general. If your vector is ever moved out of global scope and is destructed, any pointers to myObject become invalid. If you're writing these functions as part of a larger project, returning a non-const pointer could lead someone to delete the return value. This will have undefined, and catastrophic, effects on the application.
I'd rewrite this as:
myObject myFunction(const vector<myObject>& objects)
{
// find the object in question and return a copy
return *iterator;
}
If you need to modify the returned myObject, store your values as pointers and allocate them on the heap:
myObject* myFunction(const vector<myObject*>& objects)
{
return *iterator;
}
That way you have control over when they're destructed.
Something like this will break your app:
g_vector<tmpClass> myVector;
tmpClass t;
t.i = 30;
myVector.push_back(t);
// my function returns a pointer to a value in myVector
std::auto_ptr<tmpClass> t2(myFunction());
Say, you have the following:
std::vector<myObject>::const_iterator first = vObj.begin();
Then the first object in the vector is: *first. To get the address, use: &(*first).
However, in keeping with the STL design, I'd suggest return an iterator instead if you plan to pass it around later on to STL algorithms.
You are storing the copies of the myObject in the vector. So I believe the copying the instance of myObject is not a costly operation. Then I think the safest would be return a copy of the myObject from your function.
Refer to dirkgently's and anon's answers, you can call the front function instead of begin function, so you do not have to write the *, but only the &.
Code Example:
vector<myObject> vec; //You have a vector of your objects
myObject first = vec.front(); //returns reference, not iterator, to the first object in the vector so you had only to write the data type in the generic of your vector, i.e. myObject, and not all the iterator stuff and the vector again and :: of course
myObject* pointer_to_first_object = &first; //* between & and first is not there anymore, first is already the first object, not iterator to it.
I'm not sure if returning the address of the thing pointed by the iterator is needed.
All you need is the pointer itself. You will see STL's iterator class itself implementing the use of _Ptr for this purpose. So, just do:
return iterator._Ptr;