std::move std::make_shared, std::make_shared_for_overwrite
https://www.geeksforgeeks.org/stdmove-in-c/
std::move - cppreference.com https://en.cppreference.com/w/cpp/utility/move
#include <iomanip>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
int main()
{
std::string str = "Salut";
std::vector<std::string> v;
// uses the push_back(const T&) overload, which means
// we'll incur the cost of copying str
v.push_back(str);
std::cout << "After copy, str is " << std::quoted(str) << '\n';
// uses the rvalue reference push_back(T&&) overload,
// which means no strings will be copied; instead, the contents
// of str will be moved into the vector. This is less
// expensive, but also means str might now be empty.
v.push_back(std::move(str));
std::cout << "After move, str is " << std::quoted(str) << '\n';
std::cout << "The contents of the vector are { " << std::quoted(v[0])
<< ", " << std::quoted(v[1]) << " }\n";
}
Possible output:
After copy, str is "Salut" After move, str is "" The contents of the vector are { "Salut", "Salut" }
// CPP program to illustrate // std::move and std::move_backward // STL library functions #include<bits/stdc++.h> // Driver code int main() { std :: vector <int> vec1 {1, 2, 3, 4, 5}; std :: vector <int> vec2 {7, 7, 7, 7, 7}; // Print elements std :: cout << "Vector1 contains :"; for(int i = 0; i < vec1.size(); i++) std :: cout << " " << vec1[i]; std :: cout << "\n"; // Print elements std :: cout << "Vector2 contains :"; for(unsigned int i = 0; i < vec2.size(); i++) std :: cout << " " << vec2[i]; std :: cout << "\n\n"; // std :: move function // move first 4 element from vec1 to starting position of vec2 std :: move (vec1.begin(), vec1.begin() + 4, vec2.begin() + 1); // Print elements std :: cout << "Vector2 contains after std::move function:"; for(unsigned int i = 0; i < vec2.size(); i++) std :: cout << " " << vec2[i]; std :: cout << "\n"; return 0; }
Vector1 contains : 1 2 3 4 5 Vector2 contains : 7 7 7 7 7 Vector2 contains after std::move function: 7 1 2 3 4
Time Complexity: O(N) (std::move operation itself takes O(1) time )
Auxiliary Space: O(N)
https://www.apiref.com/cpp-zh/cpp/algorithm/move.html
std::move
定义于头文件
<algorithm> |
||
(1) | ||
template< class InputIt, class OutputIt >
OutputIt move( InputIt first, InputIt last, OutputIt d_first ); |
(C++11 起) (C++20 前) |
|
template< class InputIt, class OutputIt >
constexpr OutputIt move( InputIt first, InputIt last, OutputIt d_first ); |
(C++20 起) | |
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardIt2 move( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first ); |
(2) | (C++17 起) |
[first, last)
中的元素到始于 d_first
的另一范围,从首元素开始逐次到末元素。此操作后被移动范围中的元素将仍然含有适合类型的合法值,但不必与移动前的值相同。policy
执行。此重载仅若 std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> (C++20 前)std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> (C++20 起) 为 true 才参与重载决议。。参数
first, last | - | 要移动的元素范围 |
d_first | - | 目标范围起始。若 d_first 在范围 [first, last) 中则行为未定义。此情况下可用 std::move_backward 代替 std::move 。 |
policy | - | 所用的执行策略。细节见执行策略。 |
类型要求 | ||
-
InputIt 必须满足遗留输入迭代器 (LegacyInputIterator) 的要求。 |
||
-
OutputIt 必须满足遗留输出迭代器 (LegacyOutputIterator) 的要求。 |
||
-
ForwardIt1, ForwardIt2 必须满足遗留向前迭代器 (LegacyForwardIterator) 的要求。 |
返回值
指向最后移动元素后一位置的迭代器( d_first + (last - first) )。
复杂度
准确移动赋值 last - first
次。
异常
拥有名为 ExecutionPolicy
的模板形参的重载按下列方式报告错误:
- 若作为算法一部分调用的函数的执行抛出异常,且
ExecutionPolicy
为标准策略之一,则调用 std::terminate 。对于任何其他ExecutionPolicy
,行为是实现定义的。 - 若算法无法分配内存,则抛出 std::bad_alloc 。
可能的实现
template<class InputIt, class OutputIt>
OutputIt move(InputIt first, InputIt last, OutputIt d_first)
{
while (first != last) {
*d_first++ = std::move(*first++);
}
return d_first;
}
|
注解
移动重叠的范围时, std::move
在移动到左侧(目标范围的起始在源范围外)时适合,而 std::move_backward
在移动到右侧(目标范围的结尾在源范围外)时适合。
std::make_shared, std::make_shared_for_overwrite - cppreference.com https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared
std::make_shared - cppreference.com http://naipc.uchicago.edu/2015/ref/cppreference/en/cpp/memory/shared_ptr/make_shared.html
std::make_shared
Defined in header
<memory> |
||
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args ); |
||
Constructs an object of type T
and wraps it in a std::shared_ptr using args
as the parameter list for the constructor of T
.
Parameters
args | - | list of arguments with which an instance of T will be constructed. |
Return value
std::shared_ptr of an instance of type T
.
Exceptions
May throw std::bad_alloc or any exception thrown by the contructor of T
. If an exception is thrown, this function has no effect.
Notes
This function typically allocates memory for the T object and for the shared_ptr's control block with a single memory allocation (it is a non-binding requirement in the Standard). In contrast, the declaration std::shared_ptr<T> p(new T(Args...))
performs at least two memory allocations, which may incur unnecessary overhead.
Moreover, f(shared_ptr<int>(new int(42)), g())
can lead to memory leak if g
throws an exception. This problem doesn't exist if make_shared
is used.
Example
#include <iostream>
#include <memory>
void foo(std::shared_ptr<int> i)
{
(*i)++;
}
int main()
{
auto sp = std::make_shared<int>(10);
foo(sp);
std::cout << *sp << std::endl;
}
Output:
11