一、move
头文件algorithm
template <class InputIterator, class OutputIterator>
OutputIterator move (InputIterator first, InputIterator last, OutputIterator result);
移动元素范围
将[first,last]范围内的元素移动到从result开始的范围。
[first,last]中元素的值被传递给result指向的元素。 调用之后,[first,last]范围内的元素将保持未指定但有效的状态。
范围不应以结果指向[first,last]范围内的元素的方式重叠。 对于此类情况,请参阅move_backward。
此函数模板的行为等效于:
template<class InputIterator, class OutputIterator>
OutputIterator move (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last) {
*result = std::move(*first);
++result; ++first;
}
return result;
}
参数
- first,last
将迭代器输入到要移动的序列中的初始位置和最终位置。 使用的范围是[first,last),它包含first和last之间的所有元素,包括first指向的元素,但不包括last指向的元素。 - result
将迭代器输出到目标序列中的初始位置。这不应指向[first,last]范围内的任何元素。
返回值
到目标范围末尾的迭代器,其中元素已被移动。
// move algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::move (ranges)
#include <utility> // std::move (objects)
#include <vector> // std::vector
#include <string> // std::string
int main () {
std::vector<std::string> foo = {"air","water","fire","earth"};
std::vector<std::string> bar (4);
// moving ranges:
std::cout << "Moving ranges...\n";
std::move ( foo.begin(), foo.begin()+4, bar.begin() );
std::cout << "foo contains " << foo.size() << " elements:";
std::cout << " (each in an unspecified but valid state)";
std::cout << '\n';
std::cout << "bar contains " << bar.size() << " elements:";
for (std::string& x: bar) std::cout << " [" << x << "]";
std::cout << '\n';
// moving container:
std::cout << "Moving container...\n";
foo = std::move (bar);
std::cout << "foo contains " << foo.size() << " elements:";
for (std::string& x: foo) std::cout << " [" << x << "]";
std::cout << '\n';
std::cout << "bar is in an unspecified but valid state";
std::cout << '\n';
return 0;
}
复杂度
第一个和最后一个之间的距离线性:对范围中的每个元素执行移动分配。
数据范围
两个范围中的对象都已修改。
异常
如果元素移动赋值或迭代器上的操作抛出则抛出。
请注意,无效参数会导致未定义的行为。
二、move_backward
头文件algorithm
template <class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 move_backward (BidirectionalIterator1 first,
BidirectionalIterator1 last,
BidirectionalIterator2 result);
向后移动元素范围
将结束时从[end,last]开始的元素移动到结束时终止的范围内。
该函数将迭代器返回到目标范围中的第一个元素。
结果范围的元素与[first,last]的顺序完全相同。 要颠倒他们的顺序,请参阅反向。
该函数首先将*(last-1)移动到*(result-1)中,然后通过前面的元素向后移动,直到第一次到达(并包括它)。
范围不应该以这样的方式重叠:结果(目标范围中的过去元素)指向范围内的元素(first,last)。对于这种情况,请参见move。
此函数模板的行为等效于:
template<class BidirectionalIterator1, class BidirectionalIterator2>
BidirectionalIterator2 move_backward ( BidirectionalIterator1 first,
BidirectionalIterator1 last,
BidirectionalIterator2 result )
{
while (last!=first) *(--result) = std::move(*(--last));
return result;
}
参数
- first,last
双向迭代器到要移动的序列中的初始和最终位置。 使用的范围是[first,last),它包含first和last之间的所有元素,包括first指向的元素,但不包括last指向的元素。 - result
双向迭代器到目标序列中的过去位置。
这不应指向范围内的任何元素(第一个,最后一个)。
返回值
到目标序列的第一个元素的迭代器,其中元素已被移动。
// move_backward example
#include <iostream> // std::cout
#include <algorithm> // std::move_backward
#include <string> // std::string
int main () {
std::string elems[10] = {"air","water","fire","earth"};
// insert new element at the beginning:
std::move_backward (elems,elems+4,elems+5);
elems[0]="ether";
std::cout << "elems contains:";
for (int i=0; i<10; ++i)
std::cout << " [" << elems[i] << "]";
std::cout << '\n';
return 0;
}
复杂度
第一个和最后一个之间的距离线性:对范围中的每个元素执行移动分配。
数据范围
两个范围中的对象都已修改。
三、swap
头文件C++98: algorithm,C++11:utility
【C++ 98】
template <class T> void swap (T& a, T& b);
【C++ 11】
header
// moved from <algorithm> to <utility> in C++11
non-array (1)
template <class T> void swap (T& a, T& b)
noexcept (is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value);
array (2)
template <class T, size_t N> void swap(T (&a)[N], T (&b)[N])
noexcept (noexcept(swap(*a,*b)));
交换两个对象的值。
【C++98】
此函数模板的行为等效于:
template <class T> void swap ( T& a, T& b )
{
T c(a); a=b; b=c;
}
请注意该函数如何涉及复制构造和两个赋值操作,这可能不是交换存储大量数据的类的内容的最有效方式,因为这些操作中的每一个通常在其大小上以线性时间操作。
大型数据类型可以提供此函数的重载版本,从而优化其性能。 值得注意的是,所有标准容器都以这样的方式对其进行专门化处理,即只交换少量内部指针而不是整个内容,使它们在恒定时间内运行。
【C++11】
此函数不再在头algorithm中定义,而是在utility中定义。
这些函数模板的行为等同于:
template <class T> void swap (T& a, T& b)
{
T c(std::move(a)); a=std::move(b); b=std::move(c);
}
template <class T, size_t N> void swap (T (&a)[N], T (&b)[N])
{
for (size_t i = 0; i<N; ++i) swap (a[i],b[i]);
}
标准库的许多组件(在std中)以非限定方式调用swap以允许调用非基本类型的自定义重载而不是此通用版本:交换的自定义重载在与它们所属的类型相同的命名空间中声明 提供通过依赖于参数的查找来选择此通用版本。
参数
a,b
两个对象,其内容被交换。
【C ++98】
类型T应是可复制构造和可分配的。
【C++11】
类型T应是可移动构造和可移动分配的(或者为版本(2)定义交换)。
返回值
没有
// swap algorithm example (C++98)
#include <iostream> // std::cout
#include <algorithm> // std::swap
#include <vector> // std::vector
int main () {
int x=10, y=20; // x:10 y:20
std::swap(x,y); // x:20 y:10
std::vector<int> foo (4,x), bar (6,y); // foo:4x20 bar:6x10
std::swap(foo,bar); // foo:6x10 bar:4x20
std::cout << "foo contains:";
for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
复杂度
非数组:常量:完全执行一个构造和两个赋值(尽管注意每个操作都依赖于它自己的复杂性)。
数组:N中的线性:每个元素执行交换操作。
数据范围
a和b都被修改。
异常
如果类型T的构造或赋值抛出则抛出。
如果T不是可移动构造且不可移动可分配,则永远不会抛出。
请注意,如果T不满足上面指定的要求(在参数中),则会导致未定义的行为。
四、swap_ranges
头文件algorithm
template <class ForwardIterator1, class ForwardIterator2>
ForwardIterator2 swap_ranges (ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2);
交换两个范围的值
将[first1,last1]范围内的每个元素的值与first2开始范围内各自元素的值进行交换。
该函数调用swap(非限定)来交换元素。
此函数模板的行为等效于:
template<class ForwardIterator1, class ForwardIterator2>
ForwardIterator2 swap_ranges (ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2)
{
while (first1!=last1) {
swap (*first1, *first2);
++first1; ++first2;
}
return first2;
}
参数
- first1,last1
将迭代器转发到要交换的序列之一的初始位置和最终位置。 使用的范围是[first1,last1],它包含first1和last1之间的所有元素,包括first1指向的元素,但不包括last1指向的元素。 - first2
将迭代器转发到要交换的其他序列中的初始位置。 使用的范围包括与范围[first1,last1]相同数量的元素。
两个范围不得重叠。
范围不得重叠。 swap应定义为以对称方式(两个顺序)交换两个迭代器类型所指向的类型。
返回值
在第二个序列中交换的最后一个元素的迭代器。
// swap_ranges example
#include <iostream> // std::cout
#include <algorithm> // std::swap_ranges
#include <vector> // std::vector
int main () {
std::vector<int> foo (5,10); // foo: 10 10 10 10 10
std::vector<int> bar (5,33); // bar: 33 33 33 33 33
std::swap_ranges(foo.begin()+1, foo.end()-1, bar.begin());
// print out results of swap:
std::cout << "foo contains:";
for (std::vector<int>::iterator it=foo.begin(); it!=foo.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "bar contains:";
for (std::vector<int>::iterator it=bar.begin(); it!=bar.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
复杂度
第一个和最后一个之间的距离线性:对范围中的每个元素执行交换操作。
数据范围
两个范围中的对象都已修改。
五、iter_swap
头文件algorithm
template <class ForwardIterator1, class ForwardIterator2>
void iter_swap (ForwardIterator1 a, ForwardIterator2 b);
两个迭代器指向的对象的交换值
交换a和b指向的元素。
该函数调用swap(非限定)来交换元素。
此函数模板的行为等效于:
template <class ForwardIterator1, class ForwardIterator2>
void iter_swap (ForwardIterator1 a, ForwardIterator2 b)
{
swap (*a, *b);
}
参数
a,b
将迭代器转发给要交换的对象。
swap应定义为交换迭代器指向的类型的值。
返回值
没有
// iter_swap example
#include <iostream> // std::cout
#include <algorithm> // std::iter_swap
#include <vector> // std::vector
int main () {
int myints[]={10,20,30,40,50 }; // myints: 10 20 30 40 50
std::vector<int> myvector (4,99); // myvector: 99 99 99 99
std::iter_swap(myints,myvector.begin()); // myints: [99] 20 30 40 50
// myvector: [10] 99 99 99
std::iter_swap(myints+3,myvector.begin()+2); // myints: 99 20 30 [99] 50
// myvector: 10 99 [40] 99
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
复杂度
常量:调用一次交换。
数据范围
两个迭代器指向的对象都被修改。
异常
如果对swap的调用抛出则抛出。
请注意,无效参数会导致未定义的行为。