题目:
这题其实可以原地合并,因为 num1 后 n 个元素为 0,可以从后往前合并。但下面的代码未考虑到这点。
注意 std::move,它其实是将参数 t 转换为一个右值引用类型,不会拷贝内存,不会释放资源,不会调用构造函数和析构函数
1 2 3 4
| template <typename T> typename std::remove_reference<T>::type&& move(T&& t) noexcept { return static_cast<typename std::remove_reference<T>::type&&>(t); }
|
以 std::vector 为例:
1 2
| std::vector<int> a = {1, 2, 3}; std::vector<int> b = std::move(a);
|
这里:std::move(a) 把 a 变成右值引用。编译器会选择 vector 的移动构造函数,而不是拷贝构造。
移动构造函数做的事:
- 把 a 的内部指针直接“偷走”,交给 b。
- 把 a 的指针设为空,避免析构时释放同一块内存。
所以最后:b 持有 {1,2,3} 的数据。a 变成空的(size()==0,但仍然是合法对象)
总结:
nums1 = std::move(vec);
- 旧内容自动释放(移动赋值内部完成)
- 新内容接管
- vec 变空
不需要自己手动调用析构函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <vector> using std::vector;
class Solution { public: void merge(vector<int> &nums1, int m, vector<int> &nums2, int n) { vector<int> vec; int i=0, j=0; while (1) { if (i < m && j < n) { if (nums1[i] <= nums2[j]) vec.push_back(nums1[i++]); else vec.push_back(nums2[j++]); } else if (i < m && j >= n) { vec.push_back(nums1[i++]); } else if (i >= m && j < n) { vec.push_back(nums2[j++]); } else { break; } } nums1 = std::move(vec); } };
|