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; 
} 

 

Output
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)  
templateclass InputIt, class OutputIt >
OutputIt move( InputIt first, InputIt last, OutputIt d_first );
(C++11 起)
(C++20 前)
templateclass InputIt, class OutputIt >
constexpr OutputIt move( InputIt first, InputIt last, OutputIt d_first );
(C++20 起)
templateclass ExecutionPolicy, class ForwardIt1, class ForwardIt2 >
ForwardIt2 move( ExecutionPolicy&& policy, ForwardIt1 first, ForwardIt1 last, ForwardIt2 d_first );
(2) (C++17 起)

 

1) 移动范围 [first, last) 中的元素到始于 d_first 的另一范围,从首元素开始逐次到末元素。此操作后被移动范围中的元素将仍然含有适合类型的合法值,但不必与移动前的值相同。
2) 同 (1) ,但按照 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>
   
 
templateclass 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

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2024-01-16 09:22  papering  阅读(7)  评论(0编辑  收藏  举报