1.不使用共享指针的情况
#include <iostream>
#include <memory>
#include <string.h>
class A{
public:
A() {
std::cout << "create A." << std::endl;
}
A(A& a) {
std::cout << "copy create A." << std::endl;
}
~A() {
std::cout << "destroy A." << std::endl;
}
private:
};
class B {
public:
B() : a_ptr_(new A()){
std::cout << "create B." << std::endl;
}
B(B& b) {
std::cout << "copy create B." << std::endl;
//a_ptr_ = new A();
//memcpy(a_ptr_, b.a_ptr_, sizeof(A));
a_ptr_ = new A(*b.a_ptr_);
}
B& operator=(const B& b) {
std::cout << "copy assignment B." << std::endl;
if(a_ptr_ != nullptr)
delete a_ptr_;
a_ptr_ = new A(*b.a_ptr_);
return *this;
}
~B() {
delete a_ptr_;
std::cout << "destroy B." << std::endl;
}
private:
//std::shared_ptr<A> a_ptr_;
A* a_ptr_;
};
int main() {
std::cout << "***b1***" << std::endl;
B b1;
std::cout << "***b2 copy construct: b2=b1***" << std::endl;
{
B b2=b1;
}
std::cout << "***b3 copy assignment: b3=b1***" << std::endl;
{
B b3;
std::cout << "---split---" << std::endl;
b3 = b1;
}
std::cout << "---end of main---" << std::endl;
}
执行结果:
***b1***
create A.
create B.
***b2 copy construct: b2=b1***
copy create B.
copy create A.
destroy A.
destroy B.
***b3 copy assignment: b3=b1***
create A.
create B.
---split---
copy assignment B.
destroy A.
copy create A.
destroy A.
destroy B.
---end of main---
destroy A.
destroy B.
- 使用共享指针的情况1(这种是有问题的)
#include <iostream>
#include <memory>
class A{
public:
A() {
std::cout << "create A." << std::endl;
}
~A() {
std::cout << "destroy A." << std::endl;
}
private:
};
class B {
public:
B() {
std::cout << "create B." << std::endl;
a_ptr_ = std::make_shared<A>();
}
B(B& b) : a_ptr_(b.a_ptr_) {
std::cout << "copy create B." << std::endl;
}
B& operator=(const B& b) {
std::cout << "copy create B." << std::endl;
a_ptr_ = b.a_ptr_;
return *this;
}
~B() {
std::cout << "destroy B." << std::endl;
}
private:
std::shared_ptr<A> a_ptr_;
};
int main() {
std::cout << "***b1***" << std::endl;
B b1;
std::cout << "***b2 copy construct: b2=b1***" << std::endl;
{
B b2=b1;
}
std::cout << "***b3 copy assignment: b3=b1***" << std::endl;
{
B b3;
std::cout << "---split---" << std::endl;
b3 = b1;
}
std::cout << "---end of main---" << std::endl;
}
执行结果:
***b1***
create B.
create A.
***b2 copy construct: b2=b1***
copy create B.
destroy B.
***b3 copy assignment: b3=b1***
create B.
create A.
---split---
copy create B.
destroy A.
destroy B.
---end of main---
destroy B.
destroy A.
注意:
这里类B中的成员函数是类A的共享指针,即使我们没有写自定义的拷贝构造和拷贝复制函数,程序也不会崩溃,但是在使用普通的类A的指针时,程序是会崩溃的.
但是这里有一个新问题:因为在拷贝构造和复制函数中只是对共享指针进行了简单赋值,也就是说它们指向的是同一块内存.当修改复制出来的类对象中的a_ptr_时,被复制的类对象中的a_ptr_也被修改;
2.1 当修改复制出来的类对象中的a_ptr_时,被复制的类对象中的a_ptr_也被修改;
#include <iostream>
#include <memory>
class A{
public:
A():m_(100) {
std::cout << "create A." << std::endl;
}
~A() {
std::cout << "destroy A." << std::endl;
}
void set_m(int value) {
m_ = value;
}
int get_m() {
return m_;
}
private:
int m_;
};
class B {
public:
B() {
std::cout << "create B." << std::endl;
a_ptr_ = std::make_shared<A>();
}
B(B& b) : a_ptr_(b.a_ptr_) {
std::cout << "copy create B." << std::endl;
}
~B() {
std::cout << "destroy B." << std::endl;
}
void reset_a() {
a_ptr_ = std::make_shared<A>();
}
void print_a_address() {
std::cout << "address of a_ptr_ pointed to: " << a_ptr_.get() << std::endl;
}
void change_a(int value) {
a_ptr_->set_m(value);
}
void print_a() {
std::cout << a_ptr_->get_m() << std::endl;
}
private:
std::shared_ptr<A> a_ptr_;
};
int main() {
std::cout << "***b1***" << std::endl;
B b1;
std::cout << "***b2 copy construct: b2=b1***" << std::endl;
{
B b2=b1;
b1.print_a();
b2.print_a();
b2.change_a(200);
b1.print_a();
b2.print_a();
}
std::cout << "---end of main---" << std::endl;
}
执行结果:
***b1***
create B.
create A.
***b2 copy construct: b2=b1***
copy create B.
100
100
200
200
destroy B.
---end of main---
destroy B.
destroy A.
可以看出:修改了b2中的a_ptr_的值以后,b1中的a_ptr_的值也被改变了.
2.2 如果在类对象b2中重新创建a_ptr_对象,则不会出现2.1中的问题;
#include <iostream>
#include <memory>
class A{
public:
A():m_(100) {
std::cout << "create A." << std::endl;
}
~A() {
std::cout << "destroy A." << std::endl;
}
void set_m(int value) {
m_ = value;
}
int get_m() {
return m_;
}
private:
int m_;
};
class B {
public:
B() {
std::cout << "create B." << std::endl;
a_ptr_ = std::make_shared<A>();
}
B(B& b) : a_ptr_(b.a_ptr_) {
std::cout << "copy create B." << std::endl;
}
~B() {
std::cout << "destroy B." << std::endl;
}
void reset_a() {
a_ptr_ = std::make_shared<A>();
}
void print_a_address() {
std::cout << "address of a_ptr_ pointed to: " << a_ptr_.get() << std::endl;
}
void change_a(int value) {
a_ptr_->set_m(value);
}
void print_a() {
std::cout << a_ptr_->get_m() << std::endl;
}
private:
std::shared_ptr<A> a_ptr_;
};
int main() {
std::cout << "***b1***" << std::endl;
B b1;
std::cout << "***b2 copy construct: b2=b1***" << std::endl;
{
B b2=b1;
b1.print_a();
b2.print_a();
b2.reset_a();
b2.change_a(200);
b1.print_a();
b2.print_a();
}
std::cout << "---end of main---" << std::endl;
}
执行:
***b1***
create B.
create A.
***b2 copy construct: b2=b1***
copy create B.
100
100
create A.
100
200
destroy B.
destroy A.
---end of main---
destroy B.
destroy A.
因此,使用共享指针虽然可以避免程序crash, 但是还是要手动对共享指针赋值,才能保证对象之间的内存的绝对分离,保证使用安全.
- 使用共享指针的情况2
#include <iostream>
#include <memory>
#include <string.h>
class A{
public:
A():m_(100) {
std::cout << "create A." << std::endl;
}
~A() {
std::cout << "destroy A." << std::endl;
}
void set_m(int value) {
m_ = value;
}
int get_m() {
return m_;
}
private:
int m_;
};
class B {
public:
B() {
std::cout << "create B." << std::endl;
a_ptr_ = std::make_shared<A>();
}
/*B(B& b) : a_ptr_(std::make_shared<A>()) {
std::cout << "copy create B." << std::endl;
memcpy(a_ptr_.get(), b.a_ptr_.get(), sizeof(A));
}*/
B(B& b) : a_ptr_(new A()) {
std::cout << "copy create B." << std::endl;
memcpy(a_ptr_.get(), b.a_ptr_.get(), sizeof(A));
}
B& operator=(const B& b) {
std::cout << "copy create B." << std::endl;
a_ptr_ = std::make_shared<A>();
memcpy(a_ptr_.get(), b.a_ptr_.get(), sizeof(A));
return *this;
}
~B() {
std::cout << "destroy B." << std::endl;
}
void reset_a() {
a_ptr_ = std::make_shared<A>();
}
void print_a_address() {
std::cout << "address of a_ptr_ pointed to: " << a_ptr_.get() << std::endl;
}
void change_a(int value) {
a_ptr_->set_m(value);
}
void print_a() {
std::cout << a_ptr_->get_m() << std::endl;
}
private:
std::shared_ptr<A> a_ptr_;
};
int main() {
std::cout << "***b1***" << std::endl;
B b1;
std::cout << "***b2 copy construct: b2=b1***" << std::endl;
{
B b2=b1;
b1.print_a();
b2.print_a();
b2.change_a(200);
b1.print_a();
b2.print_a();
}
std::cout << "***b3 copy assignment: b3=b1***" << std::endl;
{
B b3;
std::cout << "---split---" << std::endl;
b3 = b1;
}
std::cout << "---end of main---" << std::endl;
}
***b1***
create B.
create A.
***b2 copy construct: b2=b1***
create A.
copy create B.
100
100
100
200
destroy B.
destroy A.
***b3 copy assignment: b3=b1***
create B.
create A.
---split---
copy create B.
create A.
destroy A.
destroy B.
destroy A.
---end of main---
destroy B.