std::unique_ptr
管理动态分配的对象,并在多个线程中共享:class MyObject {
public:
void doSomething() {
// ...
}
};
void threadFunc(std::unique_ptr obj) {
obj->doSomething();
}
int main() {
std::unique_ptr obj(new MyObject());
std::thread t1(threadFunc, std::move(obj));
std::thread t2(threadFunc, std::move(obj));
t1.join();
t2.join();
// obj会在离开作用域时自动释放内存
return 0;
}
在这个例子中,MyObject
对象被动态分配,并使用 std::unique_ptr
管理其生命周期。然后,两个线程分别使用 std::move
将 std::unique_ptr
转移给线程函数 threadFunc
,并在函数中使用对象。由于 std::unique_ptr
是独占所有权的智能指针,因此在转移后,原始的 std::unique_ptr
将不再拥有对象的所有权(这里是直接夺权了吗?如何证明 t2 夺取了 t1 的独占式智能指针的使用权),避免了多个线程同时访问同一个对象的问题。(那如果后续t1又要使用,会夺取回去吗?)
std::shared_ptr
管理动态分配的对象,并在多个线程中共享:class MyObject {
public:
void doSomething() {
// ...
}
};
void threadFunc(std::shared_ptr obj) {
obj->doSomething();
}
int main() {
std::shared_ptr obj(new MyObject());
std::thread t1(threadFunc, obj);
std::thread t2(threadFunc, obj);
t1.join();
t2.join();
// obj会在离开作用域时自动释放内存
return 0;
}
在这个例子中,MyObject
对象被动态分配,并使用 std::shared_ptr
管理其生命周期。然后,两个线程分别使用 std::shared_ptr
共享对象,并在函数中使用对象。由于 std::shared_ptr
是共享所有权的智能指针,因此多个线程可以同时访问同一个对象,由智能指针来管理对象的生命周期,避免了多个线程同时访问或释放同一个对象的问题。(如何使用 gdb 确认当前智能共享指针引用计数)
这些例子展示了智能指针的更复杂的用法,包括在多线程编程中共享资源、使用独占所有权和共享所有权的智能指针等。智能指针是一种非常有用的C++语言特性,可以提高程序的健壮性和可维护性。
以下是更复杂的例子,展示了智能指针的使用场景:
std::unique_ptr
管理动态分配的对象,并在类中使用:class MyClass {
public:
MyClass(std::unique_ptr obj) : m_obj(std::move(obj)) {}
private:
std::unique_ptr m_obj;
};
int main() {
std::unique_ptr obj(new MyObject());
MyClass myClass(std::move(obj));
// obj会在离开作用域时自动释放内存
return 0;
}
在这个例子中,MyObject
对象被动态分配,并使用 std::unique_ptr
管理其生命周期。然后,std::unique_ptr
被转移给类 MyClass
的成员变量 m_obj
,由智能指针来管理对象的生命周期,避免了手动释放内存的问题。
std::shared_ptr
管理动态分配的对象,并在类中使用:class MyClass {
public:
MyClass(std::shared_ptr obj) : m_obj(obj) {}
private:
std::shared_ptr m_obj;
};
int main() {
std::shared_ptr obj(new MyObject());
MyClass myClass(obj);
// obj会在离开作用域时自动释放内存
return 0;
}
在这个例子中,MyObject
对象被动态分配,并使用 std::shared_ptr
管理其生命周期。然后,std::shared_ptr
被传递给类 MyClass
的成员变量 m_obj
,由智能指针来管理对象的生命周期,避免了手动释放内存的问题。
std::unique_ptr
管理动态分配的对象,并在容器中存储:std::vector> vec;
vec.push_back(std::unique_ptr(new MyObject()));
// vec会在离开作用域时自动释放内存
在这个例子中,MyObject
对象被动态分配,并使用 std::unique_ptr
管理其生命周期。然后,std::unique_ptr
被转移给容器 std::vector
,由智能指针来管理对象的生命周期,避免了手动释放内存的问题。
std::shared_ptr
管理动态分配的对象,并在容器中存储:std::vector> vec;
vec.push_back(std::shared_ptr(new MyObject()));
// vec会在离开作用域时自动释放内存
在这个例子中,MyObject
对象被动态分配,并使用 std::shared_ptr
管理其生命周期。然后,std::shared_ptr
被传递给容器 std::vector
,由智能指针来管理对象的生命周期,避免了手动释放内存的问题。
这些例子展示了智能指针的更复杂的用法,包括在类中使用、在容器中存储等。
以下是更复杂的例子,展示了智能指针的使用场景:
std::unique_ptr
管理动态分配的对象,并在异常发生时自动释放内存:void foo() {
std::unique_ptr obj(new MyObject());
// do some operations on obj
if (someCondition) {
throw std::runtime_error("something went wrong");
}
// obj会在离开作用域时自动释放内存
}
int main() {
try {
foo();
} catch (const std::exception& e) {
// handle exception
}
return 0;
}
在这个例子中,MyObject
对象被动态分配,并使用 std::unique_ptr
管理其生命周期。然后,在函数 foo
中进行一些操作,如果发生异常,则会在函数退出时自动释放内存,避免了内存泄漏的问题。
std::shared_ptr
管理动态分配的对象,并在异常发生时自动释放内存:void foo() {
std::shared_ptr obj(new MyObject());
// do some operations on obj
if (someCondition) {
throw std::runtime_error("something went wrong");
}
// obj会在离开作用域时自动释放内存
}
int main() {
try {
foo();
} catch (const std::exception& e) {
// handle exception
}
return 0;
}
在这个例子中,MyObject
对象被动态分配,并使用 std::shared_ptr
管理其生命周期。然后,在函数 foo
中进行一些操作,如果发生异常,则会在函数退出时自动释放内存,避免了内存泄漏的问题。
std::weak_ptr
避免循环引用:class B;
class A {
public:
void setB(std::shared_ptr b) {
m_b = b;
}
private:
std::weak_ptr m_b;
};
class B {
public:
void setA(std::shared_ptr a) {
m_a = a;
}
private:
std::weak_ptr m_a;
};
int main() {
std::shared_ptr a(new A());
std::shared_ptr b(new B());
a->setB(b);
b->setA(a);
// a和b会在离开作用域时自动释放内存,避免循环引用导致的内存泄漏
return 0;
}
在这个例子中,类 A
和 B
互相引用,如果使用 std::shared_ptr
相互持有,会导致循环引用,从而导致内存泄漏。为了避免这个问题,可以使用 std::weak_ptr
来解决循环引用的问题,避免内存泄漏。
这些例子展示了智能指针的更复杂的用法,包括异常安全、避免循环引用等。
std::unique_ptr
管理动态分配的对象,并在lambda表达式中使用:std::unique_ptr obj(new MyObject());
auto lambda = [ptr = std::move(obj)]() {
// do some operations on ptr
};
// obj会在离开作用域时自动释放内存
在这个例子中,MyObject
对象被动态分配,并使用 std::unique_ptr
管理其生命周期。然后,使用 std::move
将 std::unique_ptr
转移给lambda表达式,并在表达式中使用对象。由于 std::unique_ptr
是独占所有权的智能指针,因此在转移后,原始的 std::unique_ptr
将不再拥有对象的所有权,避免了手动释放内存的问题。
std::shared_ptr
管理动态分配的对象,并在lambda表达式中使用:std::shared_ptr obj(new MyObject());
auto lambda = [ptr = obj]() {
// do some operations on ptr
};
// obj会在离开作用域时自动释放内存
在这个例子中,MyObject
对象被动态分配,并使用 std::shared_ptr
管理其生命周期。然后,使用 std::shared_ptr
传递给lambda表达式,并在表达式中使用对象。由于 std::shared_ptr
是共享所有权的智能指针,因此多个lambda表达式可以同时访问同一个对象,由智能指针来管理对象的生命周期,避免了多个lambda表达式同时访问或释放同一个对象的问题。