一、C++中移动语义和拷贝语义的区别
区别
- 拷贝语义:在赋值或函数参数传递等操作时,会创建对象的一个完整副本。这意味着会分配新的内存空间,把原对象的数据复制到新内存中。如果对象数据量很大,复制操作会消耗较多资源(如时间、内存)。
- 移动语义:是C++ 11引入的概念,用于优化对象资源所有权的转移。它不是复制数据,而是将资源的所有权从一个对象转移到另一个对象,避免了不必要的数据复制,特别是对于那些管理资源(如堆内存、文件句柄等)的对象,能大大提高性能。
如
#include <iostream>
#include <vector>
// 拷贝语义示例函数
void func_copy(std::vector<int> v) {
// 函数内部使用副本,不会影响原对象
std::cout << "拷贝语义函数内vector大小:" << v.size() << std::endl;
}
// 移动语义示例函数
void func_move(std::vector<int> &&v) {
// 函数接收右值引用,原对象资源被转移过来
std::cout << "移动语义函数内vector大小:" << v.size() << std::endl;
}
int main() {
std::vector<int> my_vector(1000);
// 拷贝语义,调用函数时会复制my_vector
func_copy(my_vector);
// 移动语义,调用函数时将my_vector资源所有权转移
func_move(std::move(my_vector));
// 此时my_vector已被移动,其状态在标准下是未指定的
// 通常其大小可能变为0,但不要依赖这种行为
std::cout << "main函数内vector大小:" << my_vector.size() << std::endl;
return 0;
}
在上述代码中, func_copy 函数体现了拷贝语义,在调用这个函数时会复制 my_vector 。 func_move 函数体现了移动语义,它接收右值引用,调用函数时原对象 my_vector 的资源所有权被转移,从而避免了复制大量数据的开销。注意在移动操作后,原对象的状态是未指定的。
二、智能指针
C++ 中的智能指针:
概念
智能指针是C++中的类模板,用于自动管理动态分配的内存。它的主要作用是防止内存泄漏,确保在适当的时候释放内存。
类型
1)shared_ptr:允许多个指针指向同一个对象,采用引用计数的方式来管理对象的生命周期。当引用计数为0时,对象会被自动销毁。
2)unique_ptr:独占所指向的对象,同一时间只能有一个unique_ptr指向一个对象,对象的所有权可以转移,但不能共享。
3)weak_ptr:是一种弱引用,主要用于配合shared_ptr解决循环引用的问题。它不控制对象的生命周期,只是观察对象是否存在。
#include <iostream>
#include <memory>
// shared_ptr示例
void sharedPtrExample() {
std::shared_ptr<int> p1 = std::make_shared<int>(10);
std::shared_ptr<int> p2 = p1;
std::cout << "p1引用计数: " << p1.use_count() << std::endl;
std::cout << "p2引用计数: " << p2.use_count() << std::endl;
}
// unique_ptr示例
void uniquePtrExample() {
std::unique_ptr<int> p1 = std::make_unique<int>(20);
// 转移所有权
std::unique_ptr<int> p2 = std::move(p1);
// 下面这行代码会出错,因为p1已经没有所有权
// std::cout << *p1 << std::endl;
if (p2) {
std::cout << *p2 << std::endl;
}
}
int main() {
sharedPtrExample();
uniquePtrExample();
return 0;
}
在这个代码中, sharedPtrExample 函数展示了 shared_ptr 的用法。 p1 和 p2 共享同一个对象,通过 use_count 函数可以查看引用计数。在 uniquePtrExample 函数里, unique_ptr 演示了对象所有权的独占性,通过 std::move 转移所有权后,原指针 p1 就不再拥有对象的控制权。
智能指针的类型:
1.std::shared_ptr
特点:采用引用计数机制。多个 shared_ptr 可以指向同一个对象,当所有指向该对象的 shared_ptr 引用计数为0时,对象才会被销毁。
#include <iostream>
#include <memory>
int main() {
// 创建一个shared_ptr,引用计数为1
std::shared_ptr<int> p1 = std::make_shared<int>(5);
std::shared_ptr<int> p2 = p1;
std::cout << "p1引用计数: " << p1.use_count() << std::endl;
// 手动释放p1,由于p2还指向对象,对象不会被销毁
p1.reset();
std::cout << "p2引用计数: " << p2.use_count() << std::endl;
// p2离开作用域,引用计数为0,对象被销毁
return 0;
}
2.std::unique_ptr
特点:独占所指向的对象,对象所有权唯一。不能进行复制,但可以转移所有权,这有效避免了资源的多重释放。
#include <iostream>
#include <memory>
int main() {
std::unique_ptr<int> p1 = std::make_unique<int>(10);
// 转移所有权,p2现在拥有对象,p1变为nullptr
std::unique_ptr<int> p2 = std::move(p1);
if (p1) {
std::cout << *p1 << std::endl;
}
if (p2) {
std::cout << *p2 << std::endl;
}
// p2离开作用域,对象被销毁
return 0;
}
3.std::weak_ptr
特点:是一种弱引用,不会增加对象的引用计数。主要用于解决 shared_ptr 循环引用的问题,它可以观察 shared_ptr 管理的对象是否存在。
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(20);
std::weak_ptr<int> wp(sp);
// 通过lock函数获取shared_ptr
if (auto shared_sp = wp.lock()) {
std::cout << "对象存在,值为: " << *shared_sp << std::endl;
} else {
std::cout << "对象不存在" << std::endl;
}
sp.reset();
if (auto shared_sp = wp.lock()) {
std::cout << "对象存在,值为: " << *shared_sp << std::endl;
} else {
std::cout << "对象不存在" << std::endl;
}
return 0;
}
标签:std,p1,对象,语义,C++,shared,拷贝,include,ptr
From: https://blog.csdn.net/2401_88249494/article/details/143983572