move-only 类型

背景

在 C++ 中,move-only 类型(move-only type)是指那些不能被复制(copy),只能通过移动(move)来传递的类型。这些类型通常会禁用拷贝构造函数和拷贝赋值运算符,并且提供移动构造函数和移动赋值运算符。

常用

  1. std::unique_ptr
    std::unique_ptr 是 C++11 引入的智能指针,它表示对动态分配内存的唯一所有权。它只能被移动,不能被拷贝。
    这意味着你不能通过拷贝构造或拷贝赋值来共享内存资源,只有通过移动操作来转移所有权。
std::unique_ptr<int> p1 = std::make_unique<int>(10);
std::unique_ptr<int> p2 = std::move(p1);  // p1 被清空,p2 现在拥有资源
  1. std::mutex
    std::mutex 是 C++11 引入的用于线程同步的对象。它表示对互斥锁的唯一所有权,不能被拷贝或赋值。
    它是 move-only 类型,因为多个线程共享同一个互斥锁对象会导致同步问题,所以不能拷贝。
std::mutex mtx1;
std::mutex mtx2 = std::move(mtx1);  // 可以通过移动来转移所有权,但不能拷贝
  1. std::unique_lock
    std::unique_lock 是 std::mutex 的一个封装,提供了更灵活的锁管理功能。它是 move-only 类型,因为它持有的锁对象不能被拷贝,只能被移动。
std::mutex mtx;
std::unique_lock<std::mutex> lock1(mtx);
std::unique_lock<std::mutex> lock2 = std::move(lock1);  // lock1 失效,lock2 现在拥有锁
  1. std::thread
    std::thread 表示一个可以执行任务的线程对象。线程对象是 move-only 类型,因为一个线程只能拥有一次执行,不能在多个对象间拷贝。
    在创建线程时,你不能拷贝线程对象,只能通过移动来传递所有权。
std::thread t1([](){ /* do something */ });
std::thread t2 = std::move(t1);  // 移动线程
  1. std::promise 和 std::future
    std::promise 和 std::future 用于线程间通信,尤其是在异步操作中传递结果。std::promise 是 move-only 类型,因为它代表一个承诺的结果,不能被复制。
    std::future 也是 move-only 类型,因为它表示未来某个时刻的结果,只能通过移动来获取。
std::promise<int> p;
std::future<int> f = p.get_future();
std::future<int> f2 = std::move(f);  // 移动 future,f 不再有效
  1. std::aligned_storage
    std::aligned_storage 是 C++ 标准库中的一个模板类,用于表示具有特定对齐要求的未初始化存储。虽然它本身并不是完全 move-only 类型,但在某些应用中,存储的对象可能是 move-only 类型,例如通过 std::aligned_storage 进行内存管理的类型。
  2. 自定义的 Move-Only 类型
    在一些情况下,你可能会自定义自己的 move-only 类型。这些类型通常会禁用拷贝构造函数和拷贝赋值运算符,并提供移动构造函数和移动赋值运算符。例如,表示文件句柄、网络连接等资源的类常常是 move-only 类型。
class MoveOnly {
public:
    MoveOnly() = default;
    MoveOnly(const MoveOnly&) = delete;  // 禁止拷贝构造
    MoveOnly& operator=(const MoveOnly&) = delete;  // 禁止拷贝赋值
    MoveOnly(MoveOnly&&) = default;  // 允许移动构造
    MoveOnly& operator=(MoveOnly&&) = default;  // 允许移动赋值
};
### 处理Java中文件只读状态下的修改或覆盖 当遇到文件设置为只读的情况,在尝试对其进行修改或覆盖时,可能会抛出`AccessDeniedException`或其他类似的异常。为了成功执行这些操作,可以采取以下几种策略: #### 方法一:更改文件权限 在尝试写入之前先检查并改变目标文件的可写属性。 ```java File file = new File(filePath); if (!file.canWrite()) { // 尝试解除只读限制 if (file.setWritable(true)) { System.out.println("已成功移除只读标志"); } else { throw new RuntimeException("无法更改编辑权限"); } } // 继续正常的数据保存逻辑... ``` 此段代码首先验证当前文件是否具有写权限[^1]。如果发现它被标记为不可编辑,则通过调用`setWritable()`函数试图更新其访问控制列表ACL以便允许后续的IO活动。 #### 方法二:复制到临时位置再替换原文件 另一种解决方案涉及将原始内容拷贝至一个新的非受限路径下完成必要的变更之后删除旧版本并将新副本重命名为原来的名称。 ```java Path source = Paths.get(originalFilePath); Path tempTarget = Files.createTempFile(null, null); try (BufferedReader reader = Files.newBufferedReader(source); BufferedWriter writer = Files.newBufferedWriter(tempTarget)) { String line; while ((line = reader.readLine()) != null) { // 对每一行数据应用所需的转换规则 writer.write(line); writer.newLine(); } } finally { // 清理工作:确保即使发生错误也能安全地交换两个文件的位置 Files.deleteIfExists(Paths.get(originalFilePath)); Files.move(tempTarget, Paths.get(originalFilePath), StandardCopyOption.REPLACE_EXISTING); } ``` 这种方法绕过了直接修改受保护资源所带来的挑战,而是选择了间接的方式达到相同的效果——即实现了对指定文档的有效更新而不违反操作系统层面的安全机制[^2]。 #### 方法三:使用高级API处理特定格式文件 对于某些类型的文件(如Excel),可以直接利用专门设计用来解析这类结构化数据集的库来进行无损编辑而无需担心底层存储介质上的权限问题。例如,Apache POI就是一个非常适合处理Office系列文档的强大工具包[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值