#include <memory>
#include <iostream>
class A
{
public:
int i = 8;
};
class B {
public:
std::unique_ptr<A> p;
};
int main()
{
B b;
b.p.reset(new A);
std::cout << "Out1: " << b.p->i << std::endl;
const A* const a = b.p.get();
delete a; // how to forbid this statement?
std::cout << "Out2: " << b.p->i << std::endl;
}
is nonsense and yields nonsense:
Out1: 8
Out2: 1587634531
free(): double free detected in tcache 2
Aborted
How to detect such nonsense at compile time, i.e. how to declare pointer a such that it has r/w access to *a (of type A), but cannot corrupt the unique pointer B.p?
The const around A* are not the solution.
In the case of std::shared_ptr, we have std::weak_ptr - do we have nothing alike for std::unique_ptr?
Per the comments, you can use a static analysis tool to forbid new/delete, setting warnings as errors, and running on pull requests on CICD. In particular, running clang-tidy on your code gives:
The warning messages reference the core guidelines, in particular I.11, and the support library. However rather than using the support library, it's easier to rewrite directly in terms of
unique_ptr,std::make_unique(as has already been mentioned), and encapsulate pointers in classes.One possible refactoring is along these lines:
Note, here
ahas become a (const) reference, so can't be deleted.Footnote: clang-tidy can be set up with CMake using
CMAKE_CXX_CLANG_TIDY, with a .clang-tidy file at the root of the project to enable or disable checks (depending on whether you want to have minimal checks, or run all checks and disable the ones that aren't useful).