Here, in the code. While I'm pushing back that obj2 to vector, is it creating another class object? Because my settings are not affecting this vector element. How can I prevent this? Is there a way to make it the same as my object and can I able to control it without explicitly calling it?
std::vector stores copies of the objects that you insert. If you don't want this you could create a vector of pointers and insert pointers to the objects instead. Note that this will not extent the lifetime of the objects automagically so be careful.
I got you. I'm learning these classes still. And deep copy constructor's purpose is to close the what did you say. I think that smart pointers are easier.
The references to the objects already in the vector would be invalidated if emplace_back triggers a reallocation. We could use an early reserve to prevent this. Or if fast random access is not a requirement, this is a canonical use case for std::list
#include <iostream>
#include <vector>
struct test
{
test( int aa = 0, int bb = 0 ) noexcept : a(aa), b(bb) {}
void print() const { std::cout << "test{a==" << a << ",b==" << b << "}\n" ; }
int get_a() constnoexcept { return a ; }
int get_b() constnoexcept { return b ; }
void set_a( int v ) noexcept { a = v ; }
void set_b( int v ) noexcept { b = v ; }
private:
int a ;
int b ;
};
int main()
{
std::vector<test> all_tests ; // empty vector
all_tests.reserve(10) ; // reserve space for ten objects (prevent reallocation)
// add two objects to the vector
all_tests.emplace_back(1,2) ; // construct test(1,2) in-place in the vector
test& obj1 = all_tests.back() ; // get a reference to the object that was added
all_tests.emplace_back() ; // default construct a test in-place in the vector
// (the capacity is adequate; so references to objects in the vector are not invalidated)
test& obj2 = all_tests.back() ; // get a reference to the second object that was added
// modify the objects in the vector
obj1.set_a(123) ;
obj1.set_b(4567) ;
obj2.set_a(888) ;
obj2.set_b(9999) ;
// print the objects in the vector
for( const test& t : all_tests ) t.print() ;
}
int main()
{
std::list<test> all_tests ; // empty list
// add two objects to the list
all_tests.emplace_back(1,2) ; // construct test(1,2) in-place in the list
test& obj1 = all_tests.back() ; // get a reference to the object that was added
all_tests.emplace_back() ; // default construct a test in-place in the list
test& obj2 = all_tests.back() ; // get a reference to the second object that was added
// modify the objects in the list
obj1.set_a(123) ;
obj1.set_b(4567) ;
obj2.set_a(888) ;
obj2.set_b(9999) ;
// print the objects in the list
for( const test& t : all_tests ) t.print() ;
}
A question is, do you really need to access an object both via obj2 and via vec.at(1)?
With std::unique_ptr, there can be only one! A unique_ptr is "unique", because it is the only pointer that points to object with intent to manage the object's lifetime.
Ensuring that there is only one smart pointer that owns an object is the responsibility of the programmer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#include <iostream>
#include <memory>
struct A
{
A() { std::cout << "construct object at " << this << '\n' ; }
~A() { std::cout << "destroy object at " << this << '\n' ; }
};
int main()
{
A* p = new A ;
std::unique_ptr<A> pa1(p) ; // hand over ownership of the object to pa1
std::unique_ptr<A> pa2(p) ; // hand over ownership of the object to pa2
// destructors of pa2, pa1 engender undefined behaviour
}
A std::vector of std::unique_ptr essentially accomplishes the same thing but has the advantage that you can freely remove and add new objects without having to worry about invalidating pointers/references to the other objects, and if you want you can even transfer the ownership of the objects (such as to another vector).
Note that just because you use std::unique_ptr doesn't mean you can't have other non-owning pointers/references to the objects. This is very common when passing objects to functions. You normally don't pass a std::unique_ptr to a function unless it deals with ownership, instead you pass the object itself by reference as normal.