Weak Pointers and Circular References in C++ 11: Listing 2
How to *not* deal with circular references in C++11.
// person.h – Buggy version (see Figure 1)
#ifndef PERSON_H_
#define PERSON_H_
#include <memory>
#include <string>
using namespace std;
class person {
friend void get_couple_married(shared_ptr<person>, shared_ptr<person>);
public:
person() = delete;
person(const string);
~person();
string get_name() const;
shared_ptr<person> get_spouse() const;
private:
string name_;
typedef shared_ptr<person> spouse_ptr;
spouse_ptr spouse_;
void set_spouse(const shared_ptr<person>);
};
#endif /* PERSON_H_ */
/* ---------------------------------- */
// person.cpp
#include "person.h"
#include <iostream>
#include <stdexcept>
using namespace std;
person::person(const string name) : name_{name} {
cout << name_ << " instance created." << endl;
}
person::~person() {
cout << name_ << " instance to be disposed." << endl;
}
string person::get_name() const { return name_; }
shared_ptr<person> person::get_spouse() const { return spouse_; }
void person::set_spouse(const shared_ptr<person> sp) {
this->spouse_ = sp;
}
void get_couple_married(shared_ptr<person> husband, shared_ptr<person> wife) {
// checks arguments aren’t null
if ((husband==nullptr)||(wife==nullptr))
throw invalid_argument("get_couple_married(husband, wife): can't get nullptr as couple member");
// checks arguments aren’t the same instance
if (husband.get()==wife.get())
throw invalid_argument("get_couple_married(husband, wife): husband and wife can't be the same person");
// Here’s where the issue is produced. Both husband and wife get each other’s shared_ptr
// targeting them
husband->set_spouse(wife);
wife->set_spouse(husband);
}
/* ---------------------------------- */
// main.cpp
#include <iostream>
#include "person.h"
using namespace std;
void get_couple_married() {
shared_ptr<person> husband = make_shared<person>("John"), wife = make_shared<person>("Pocahontas");
get_couple_married(husband, wife);
cout << husband->get_name() << "'s wife is " << husband->get_spouse()->get_name() << "." << endl;
cout << wife->get_name() << "'s husband is " << wife->get_spouse()->get_name() << "." << endl;
}
int main() {
get_couple_married();
return 0;
}
About the Author
Diego Dagum is a software architect and developer with more than 20 years of experience. He can be reached at [email protected].