I am mostly self thought with C++ and I have built some large complex codes during my PhD research. One of the issues I have been continuously facing is lack of oversight during development as I am nearly the only one who can code in the entire group. So when I make a "bad" code, there's no one to correct me and make me kick off a bad habit.
Question I have regards the following scenario:
I need to solve several iterative systems of equations for Physics problem I am studying. The package I built has around 30 classes and when I reviewed my code I noticed that I often unnecessarily copy objects. Consider this example:
class A
{
std::valarray<double> _someArray;
public:
const double doSomethingComplicated() const;
A(const std::valarray<double> &someArray) : _someArray(someArray) {...};
}
class B
{
A _objectA;
public:
const double doSomethingComplicatedWithObjectA() const;
B(const A &objectA) : _objectA(objectA) {...};
}
class C
{
A _objectA;
B _objectB;
public:
const double doSomethingComplicatedWithObjectAandB() const;
C(const A &objectA, const B &objectB) : _objectA(objectA), _objectB(objectB) {...};
}
Disregard constructor definition in class declaration and what ... code in constructor is. The point is, in more complex classes as B and C, I am making private fields of previously made objects and in their constructors I am making copies of them. A lot of classes in my project do not change, so first time I make class A object, that will be it till the of code. I feel by making class A fields in more complex objects I am unnecessarily creating copies of A, even if it is just a "shallow" copy. I feel I can make much better code if I did this:
class B
{
public:
const double doSomethingComplicatedWithObjectA(const A &objectA) const;
B() {...};
};
class C
{
public:
const double doSomethingComplicatedWithObjectAandB(const A &objectA, const B &objectB) const;
C() {...};
};
In this case I would pass references of objects A and B to methods of more complex classes when something is needed. So there won't be an unnecessary copy and the same chunk of memory would be used. Obvious issue is that I may have 10 methods that need object A, and every time method needs object B, I also need to pass object A in those methods as B depends on A. So I may end up with very messy code, and feel that's not the way to go.
What would be a good recommendation to handle code like this?
My gut feeling is to use pointers, for instance in class C, I could have A* and B* fields, but I am then unsure how to write constructors properly and if I need to do some destructor management. I clearly don't have much experience with pointer fields, and my fields are either stuff from STL or other libraries, so I rarely need to implement destructors. If C has A* field, how do I make sure its destructor does not delete A object. I only want A* pointer to point to A object wherever it is in memory when first created by some other code, and that code that creates it, will automatically destroy it, not class C, class C just needs to stop pointing at that chunk of memory when C is destroyed.
Another feeling I have is to use shared or other types of smart pointers, but I understand those even less. I think the problem is my understanding of pointers and my lack of experience with them.
In essence my issue is in understanding C++ as I have no one to ask, and literature feels overwhelming, which is why I am here.