array、tuple、string、vector的使用
array
参考https://blog.csdn.net/zhengqijun_/article/details/81566109
array是一个保存N 个 T 类型元素的序列式容器,连续存储且大小固定,内部不保留额外的数据(只有N个T类型对象),跟数组差不多,只是添加了一些成员函数和全局函数。
- 形参 N 必须是一个常量表达式
- array容器相比于原始数组的优点:
1.array 容器提供的 at() 成员函数,可以有效防止越界操纵数组的情况,这也就意味着数组容器可以作为参数传给函数,而不再需要单独去指定数组元素的个数。
2.fill() 函数可以实现数组的快速初始化;
3.swap() 函数可以轻松实现两个相同数组(类型相同,大小相同)中元素的互换
4.当两个 array 容器满足大小相同并且保存元素的类型相同时,两个 array 容器可以直接直接做赋值操作,即将一个容器中的元素赋值给另一个容器。
5.当两个 array 容器满足大小相同并且保存元素的类型相同时,如果其保存的元素也支持比较运算符,就可以用任何比较运算符直接比较两个 array 容器
类模板声明
template < class T, size_t N >
class array;
头文件
#include< array>
示例
#include<array>
#include<iostream>
using namespace std;
int main(){
//初始化
array<int,5> first;
array<int,5> second={1,2,3,4,5};
array<int,5> three(second);
//array大小
cout << "sizeof(first) = " << sizeof(first) << endl;
cout << "size of array = " << first.size() << endl;
cout << "max_size of array = " << first.max_size() << endl;
//访问
cout << "three[0] = " << three[0]<< endl;
cout << "three.at(1) = " << three.at(1) << endl;
//返回three中第一个元素的地址
cout<<"& three= "<<three.data()<<endl;
//遍历
for(array<int,5>::iterator it=three.begin();it<three.end();it++){
cout<<*it<<" ";
}
cout<<endl;
for(auto& i:three)
cout<<i<<" ";
cout<<endl;
//修改
three[0]=2;
cout<<"three[0]= "<<three[0]<<endl;
//填充
array<int,5> four;
four.fill(6);
for(auto& j:four)
cout<<j<<" ";
cout<<endl;
//交换两个array
three.swap(four);
for(auto& k:three)
cout<<k<<" ";
cout<<endl;
system("pause");
return 0;
}
tuple
参考:https://blog.csdn.net/fengbingchun/article/details/72835446
tuple:元组,
tuple是类似pair的模板,只是std::tuple可以有任意数量的成员
关于pair,
头文件为 #include < utility >
头文件
#include <tuple>
类模板声明
template< class... Types >
class tuple;
初始化
- make_tuple,函数模板,用于构造一个合适的tuple
//初始化
tuple<int,char,string> first;
tuple<int,char,string> second(make_tuple(2,'t',"two"));
tuple<int,char,string> three(3,'t',"three");
tuple<int,char,string> four(three);
访问
- get,模板函数,返回tuple中第Ith个元素的引用
template< std::size_t I, class... Types >
typename std::tuple_element<I, tuple<Types...> >::type&
get( tuple<Types...>& t ) noexcept;
//读取下标0,1,2处的值
cout<<" three contains: "<<get<0>(three)<<","
<<get<1>(three)<<","<<get<2>(three)<<endl;
std::tuple_element
tuple_element是一个模板类,其type用于萃取tuple中第Ith个元素的类型
template< std::size_t I, class... Types >
class tuple_element< I, tuple<Types...> >;
示例
auto mytuple = std::make_tuple(10, 'a');
std::tuple_element<0, decltype(mytuple)>::type first =std::get<0>(mytuple);
std::tuple_element<1, decltype(mytuple)>::type second = std::get<1>(mytuple);
std::cout << "mytuple contains: " << first << " and " <<second << '\n';
关于decltype
参考:C++11:类型处理(using、auto、decltype)decltype与auto关键字一样,用于进行编译时类型推导,不过它与auto还是有一些区别的。decltype的类型推导并不是像auto一样是从变量声明的初始化表达式获得变量的类型,而是总是以一个普通表达式作为参数,返回该表达式的类型,而且decltype并不会对表达式进行求值。
std::tuple_size
tuple_size是一个类模板,其成员变量value用于获取tuple中元素的个数
示例
template< class... Types >
class tuple_size< std::tuple<Types...> >
: public std::integral_constant<std::size_t, sizeof...(Types)> { };
std::tuple<int, char, double> mytuple(10, 'a', 3.14);
std::cout << "mytuple has ";
std::cout << std::tuple_size<decltype(mytuple)>::value;
std::cout << " elements." << '\n';
string
参考:https://blog.csdn.net/zy2317878/article/details/79056289
类模板声明
template<
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
> class basic_string;
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;
头文件
#include <string>
初始化
//默认构造
string ();
//复制构造
string (const string& str);
//范围构造
string (const string& str, size_t pos, size_t len = npos);
//由C风格的 char* 构造
string (const char* s);
//由s的前n个字符组成的字符串构造
string (const char* s, size_t n);
//n个字符c填充
string (size_t n, char c);
//迭代器范围构造
template <class InputIterator>
string (InputIterator first, InputIterator last);
//初始化列表构造
string (initializer_list<char> il);
//常量字符串构造
string (string&& str) noexcept;
示例:
// http://www.cplusplus.com/reference/string/string/string/
#include <iostream>
#include <string>
int main ()
{
std::string s0 ("Initial string");
// constructors used in the same order as described above:
std::string s1;
std::string s2 (s0);
std::string s3 (s0, 8, 3);
std::string s4 ("A character sequence");
std::string s5 ("Another character sequence", 12);
std::string s6a (10, 'x');
std::string s6b (10, 42); // 42 is the ASCII code for '*'
std::string s7 (s0.begin(), s0.begin()+7);
std::cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3;
std::cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6a: " << s6a;
std::cout << "\ns6b: " << s6b << "\ns7: " << s7 << '\n';
return 0;
}
插入
- append():在字符串末尾附加字符串
- operator+=:尾部附加字符串
//string (1)
string& operator+= (const string& str);
//c-string (2)
string& operator+= (const char* s);
//character (3)
string& operator+= (char c);
//initializer list (4)
string& operator+= (initializer_list<char> il);
示例
// string::operator+=
#include <iostream>
#include <string>
int main ()
{
std::string name ("John");
std::string family ("Smith");
name += " K. "; // c-string
name += family; // string
name += '\n'; // character
std::cout << name;
return 0;
}
- push_back:添加字符到字符串末尾
void push_back (char c);
-
assign():将新的字符串赋值给原字符串
-
operator=:将新的字符串赋值给原字符串
-
insert():在pos指定的位置之前插入字符串
//在pos指定的位置之前插入整个字符串str
string& insert (size_t pos, const string& str);
//在pos指定的位置之前插入字符串str中由subpos sublen指定的子串
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
//在pos指定的位置之前插入整个const char*表示的C类型字符串
string& insert (size_t pos, const char* s);
//在pos指定的位置之前插入整个const char*表示的C类型字符串s中的前n个字符组成的字符串
string& insert (size_t pos, const char* s, size_t n);
//在指定的位置之前插入n个字符c
string& insert (size_t pos, size_t n, char c);
iterator insert (const_iterator p, size_t n, char c);
iterator insert (const_iterator p, char c);
//范围插入
template <class InputIterator>
iterator insert (iterator p, InputIterator first, InputIterator last);
string& insert (const_iterator p, initializer_list<char> il);
insert示例:
// inserting into a string
#include <iostream>
#include <string>
int main ()
{
std::string str="to be question";
std::string str2="the ";
std::string str3="or not to be";
std::string::iterator it;
// used in the same order as described above:
str.insert(6,str2); // to be (the )question
str.insert(6,str3,3,4); // to be (not )the question
str.insert(10,"that is cool",8); // to be not (that is )the question
str.insert(10,"to be "); // to be not (to be )that is the question
str.insert(15,1,':'); // to be not to be(:) that is the question
it = str.insert(str.begin()+5,','); // to be(,) not to be: that is the question
str.insert (str.end(),3,'.'); // to be, not to be: that is the question(...)
str.insert (it+2,str3.begin(),str3.begin()+3); // (or )
std::cout << str << '\n';
return 0;
}
遍历
- 基于迭代器遍历
string str ("Test string");
for ( string::iterator it=str.begin(); it!=str.end(); ++it)
cout << *it;
- 基于for范围遍历
for(auto& i:str)
cout<<i;
访问
-
通过 [] 来访问
-
通过at()访问
-
back()返回最后一个字符的引用
-
front()返回第一个字符的引用
示例
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str ("one two three,go!");
for ( int i=0;i<str.size();i++)
cout<<str[i];
cout << '\n';
//索引越界,at()抛出out_of_range异常
for(int j=0;j<str.size();j++)
cout<<str.at(j);
cout<<endl;
cout<<str.front()<<endl;
cout<<str.back()<<endl;
system("pause");
return 0;
}
查找
- find:在字符串中查找内容。在字符串中搜索由其参数指定的字符串序列的第一次出现(需要整个序列完全匹配)。当指定pos时,搜索仅包括位置pos处及之后的字符。
返回值:首次匹配的第一个字符的位置。如果没有找到匹配,返回string :: npos。
https://blog.csdn.net/zy2317878/article/details/79056289
// string::find
#include <iostream> // std::cout
#include <string> // std::string
int main ()
{
std::string str ("There are two needles in this haystack with needles.");
std::string str2 ("needle");
// different member versions of find in the same order as above:
std::size_t found = str.find(str2);
if (found!=std::string::npos)
std::cout << "first 'needle' found at: " << found << '\n';
found=str.find("needles are small",found+1,6);
if (found!=std::string::npos)
std::cout << "second 'needle' found at: " << found << '\n';
found=str.find("haystack");
if (found!=std::string::npos)
std::cout << "'haystack' also found at: " << found << '\n';
found=str.find('.');
if (found!=std::string::npos)
std::cout << "Period found at: " << found << '\n';
// let's replace the first needle:
str.replace(str.find(str2),str2.length(),"preposition");
std::cout << str << '\n';
return 0;
//Output
//first 'needle' found at: 14
//second 'needle' found at: 44
//'haystack' also found at: 30
//Period found at: 51
//There are two prepositions in this haystack with needles
}
- find_ first_ of:在字符串中查找字符。在字符串中搜索与其参数中指定的任何字符匹配的第一个字符。当指定pos时,搜索仅包括位置pos及之后的字符。请注意,对于序列中的一个字符来说,就足够了(不是全部)
// string::find_first_of
#include <iostream> // std::cout
#include <string> // std::string
#include <cstddef> // std::size_t
int main ()
{
std::string str ("Please, replace the vowels in this sentence by asterisks.");
std::size_t found = str.find_first_of("aeiou");
//下面的循环实现了找到str中,”aeiou“中所有字符:'a''e''i''o''u',并将其都替换为'* '
while (found!=std::string::npos)
{
str[found]='*';
found=str.find_first_of("aeiou",found+1);
}
std::cout << str << '\n';
return 0;
//Output:
//Pl**s*, r*pl*c* th* v*w*ls *n th*s s*nt*nc* by *st*r*sks.
}
- find_ first_ not_of:查找字符串中没有字符。在字符串中搜索与其参数中指定的任何字符不匹配的第一个字符。指定pos时,搜索仅包含位置pos及之后的字符。
// string::find_first_not_of
#include <iostream> // std::cout
#include <string> // std::string
#include <cstddef> // std::size_t
int main ()
{
std::string str ("look for non-alphabetic characters...");
std::size_t found = str.find_first_not_of("abcdefghijklmnopqrstuvwxyz ");
//下面的代码就是实现找到str中非小写字母的字符,即'-',并返回'-'的位置。
if (found!=std::string::npos)
{
std::cout << "The first non-alphabetic character is " << str[found];
std::cout << " at position " << found << '\n';
}
return 0;
//Output:
//The first non-alphabetic character is - at position 12
}
- find_ last_of:从结尾查找字符串。在字符串中搜索与其参数中指定的任何字符匹配的最后一个字符。当pos被指定时,搜索只包含位置pos之前或之前的字符,忽略pos之后的任何可能的事件。
// string::find_last_of
#include <iostream> // std::cout
#include <string> // std::string
#include <cstddef> // std::size_t
void SplitFilename (const std::string& str)
{
std::cout << "Splitting: " << str << '\n';
//注意'\\'是反斜杠的转义字符表示,表示一个字符
std::size_t found = str.find_last_of("/\\"); //在str中搜索与"/\\"中任一个字符匹配的最后一个字符。
std::cout << " path: " << str.substr(0,found) << '\n'; //pos就是匹配到的位置。0~pos
std::cout << " file: " << str.substr(found+1) << '\n'; //pos~string结束
}
int main ()
{
std::string str1 ("/usr/bin/man");
std::string str2 ("c:\\windows\\winhelp.exe");
SplitFilename (str1);
SplitFilename (str2);
// \\Output
// \\Splitting: /usr/bin/man
// \\ path: /usr/bin
// \\ file: man
// \\Splitting: c:\windows\winhelp.exe
// \\ path: c:\windows
// \\ file: winhelp.exe
system("pause");
return 0;
}
删除
- erase:删除pos位置或迭代器处的元素
//删除以下标pos开头的长度为len的子串
string& erase (size_t pos = 0, size_t len = npos);
iterator erase (const_iterator p);
//范围删除
iterator erase (const_iterator first, const_iterator last);
// string::erase
#include <iostream>
#include <string>
int main ()
{
std::string str ("This is an example sentence.");
std::cout << str << '\n';
// "This is an example sentence."
str.erase (10,8); // ^^^^^^^^
std::cout << str << '\n';
// "This is an sentence."
str.erase (str.begin()+9); // ^
std::cout << str << '\n';
// "This is a sentence."
str.erase (str.begin()+5, str.end()-9); // ^^^^^
std::cout << str << '\n';
// "This sentence."
return 0;
}
- pop_back:删除最后一个字符
void pop_back();
- clear:清空字符串
void clear();
反转字符串
反转字符串
注意:string类本身并没有提供用于反转的成员函数
要实现字符串反转得使用algorithm中的reverse函数
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last);
功能:
反转区间[first,last)的元素,注意是左闭右开区间
使用示例
#include <iostream>
#include <string> //string
#include<cstring> // strlen
#include <algorithm>//reverse
using namespace std;
int main()
{
//反转string
string s1 = "hello world";
reverse(s1.begin(),s1.end());
cout<<"reverse string: "<<s1<<endl;
//char *s2="I am a char array,not a char pointer";不能反转字符指针指向的字符串(字符串常量)
//反转字符数组
char s2[]="I am a char array,not a char pointer";
reverse(s2,s2+strlen(s2));
cout<<"reverse char array: "<<s2<<endl;
system("pause");
return 0;
}
std::getline()从流中获取一行字符串
std::getline用于从流stream中获取一行字符串,赋值给string。记住,这是一个很好用的函数,特别适合从键盘输入流或者文件流中去获取多行数据。
http://www.cplusplus.com/reference/string/string/getline/?kw=getline
//getline的两种用法如下
istream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);
// extract to string
#include <iostream>
#include <string>
int main ()
{
std::string name;
std::cout << "Please, enter your full name: ";
std::getline (std::cin,name);
std::cout << "Hello, " << name << "!\n";
return 0;
}
其他
- c_str:获取C风格字符串
http://www.cplusplus.com/reference/string/string/c_str/
const char* c_str() const noexcept;
注意const char* 不能用于初始化char *类型的实体.
如下代码会提示错误
const char *str;
char *p=str;
提示错误:指向const的指针不能被赋给指向非const的指针,所以应该用strcpy,也就是另开一块内存,把字符一个个复制过去
const char *expr = “abcd”;
char *buf = new char[strlen(expr)+1];
strcpy(buf, expr);
示例
// strings and c-strings
#include <iostream>
#include <cstring>
#include <string>
int main ()
{
std::string str ("Please split this sentence into tokens");
char * cstr = new char [str.length()+1];
std::strcpy (cstr, str.c_str());
// cstr now contains a c-string copy of str
char * p = std::strtok (cstr," ");
while (p!=0)
{
std::cout << p << '\n';
p = std::strtok(NULL," ");
}
delete[] cstr;
return 0;
}
- copy:从字符串复制字符序列
- replace:替换字符串的一部分。将以pos开头的长度为len的字符串部分(或[i1,i2之间的范围内的字符串部分)替换成新的字符串
// replacing in a string
#include <iostream>
#include <string>
int main ()
{
std::string base="this is a test string.";
std::string str2="n example";
std::string str3="sample phrase";
std::string str4="useful.";
// replace signatures used in the same order as described above:
// Using positions: 0123456789*123456789*12345
std::string str=base; // "this is a test string."
str.replace(9,5,str2); // "this is an example string." (1)
str.replace(19,6,str3,7,6); // "this is an example phrase." (2)
str.replace(8,10,"just a"); // "this is just a phrase." (3)
str.replace(8,6,"a shorty",7); // "this is a short phrase." (4)
str.replace(22,1,3,'!'); // "this is a short phrase!!!" (5)
// Using iterators: 0123456789*123456789*
str.replace(str.begin(),str.end()-3,str3); // "sample phrase!!!" (1)
str.replace(str.begin(),str.begin()+6,"replace"); // "replace phrase!!!" (3)
str.replace(str.begin()+8,str.begin()+14,"is coolness",7); // "replace is cool!!!" (4)
str.replace(str.begin()+12,str.end()-4,4,'o'); // "replace is cooool!!!" (5)
str.replace(str.begin()+11,str.end(),str4.begin(),str4.end());// "replace is useful." (6)
std::cout << str << '\n';
return 0;
}
- substr:生成子字符串
// string::substr
#include <iostream>
#include <string>
int main ()
{
std::string str="We think in generalities, but we live in details.";
// (quoting Alfred N. Whitehead)
std::string str2 = str.substr (3,5); // "think"
std::size_t pos = str.find("live"); // position of "live" in str 返回pos类型size_t
std::string str3 = str.substr (pos); // get from "live" to the end
std::cout << str2 << ' ' << str3 << '\n';
return 0;
//Output:
//think live in details.
}
- compare:比较字符串
// comparing apples with apples
#include <iostream>
#include <string>
int main ()
{
std::string str1 ("green apple");
std::string str2 ("red apple");
if (str1.compare(str2) != 0) //!=0成立
std::cout << str1 << " is not " << str2 << '\n';
if (str1.compare(6,5,"apple") == 0) //==0成立
std::cout << "still, " << str1 << " is an apple\n";
if (str2.compare(str2.size()-5,5,"apple") == 0) //==0成立
std::cout << "and " << str2 << " is also an apple\n";
if (str1.compare(6,5,str2,4,5) == 0) //==0成立
std::cout << "therefore, both are apples\n";
return 0;
}
数字和字符串之间转换
来自http://c.biancheng.net/view/1527.html
http://www.cplusplus.com/reference/string/
C++ 11 提供了若干 to_string(T value) 函数来将 T 类型的数字值转换为字符串形式。
以下是几个 to_string() 函数的列表:
头文件
<string>
http://www.cplusplus.com/reference/string/to_string/?kw=to_string
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
字符串到数字的转换可以通过 stoX() 系列函数来执行。该系列函数的成员可以将字符串转换为 int、long、float 和 double 类型的数字。具体语法如下所示:
int stoi(const strings str, size_t* pos = 0, int base = 10)
long stol(const strings str, size_t* pos = 0, int base = 10)
float stof(const strings str, size_t* pos = 0)
double stod(const strings str, size_t* pos = 0)
第一个形参 str 是一个字符串(例如 “-342” 或 “3.48” 等),它将被转换为恰当的数字形式。这些函数可以将 str 可能的最长前缀转换为数字,并返回一个整数地址 pos,pos 中保存了 str 无法被转换的第一个字符的索引。类型 size_t 是在标准库中定义的,常用于表示无符号整数的大小或数组、矢量、字符串中的一个索引。
例如,如果试图转换字符串 “-34iseven”,则将成功返回整数 -34,而无法转换的第一个字符的位置 pos 则被设置为 3。base 形参仅适用于整数转换,指示用于转换的进制。pos 和 base 形参都是可选的,所以它们可以被忽略。如果 pos 被忽略,则不会存储停止字符的索引。如果 base 被忽略,则默认为十进制。如果字符串 str 包含一个无效值,例如 “is-34 even?”,则不会进行转换,函数将抛出一个 invalid_argument 异常。
vector
参考:http://www.cplusplus.com/reference/vector/vector/
vector是一个能够存放任意类型的动态数组,它也适用于标准库中的多种算法。
类模板声明
template<
class T,
class Allocator = std::allocator<T>
> class vector;
头文件
#include<vector>
初始化
//默认无参构造
explicit vector (const allocator_type& alloc = allocator_type());
//有参构造,用n个0填充
explicit vector (size_type n);
//有参构造,用n个val填充
vector (size_type n, const value_type& val,
const allocator_type& alloc = allocator_type());
//迭代器范围构造,左闭右开区间[first,last)
template <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
//复制构造
vector (const vector& x);
vector (const vector& x, const allocator_type& alloc);
//移动复制构造
vector (vector&& x);
vector (vector&& x, const allocator_type& alloc);
//初始化列表
vector (initializer_list<value_type> il,
const allocator_type& alloc = allocator_type());
示例
//默认无参构造
vector<int> first;
//
vector<int> second(4);
vector<int> three(4,1);
//迭代器范围构造
vector<int> four(three.begin(),three.end());
//复制构造
vector<int> five(three);
//初始化列表构造
vector<int> six({1,2,3,4});
插入
- insert
//在pos位置前插入value
iterator insert( iterator pos, const T& value );
//在pos前插入count个value
void insert( iterator pos, size_type count, const T& value );
//在pos前插入范围[first,last]的值
template< class InputIt >
void insert( iterator pos, InputIt first, InputIt last);
#include <iostream>
#include <vector>
void print_vec(const std::vector<int>& vec)
{
for (auto x: vec) {
std::cout << ' ' << x;
}
std::cout << '\n';
}
int main ()
{
std::vector<int> vec(3,100);
print_vec(vec);
auto it = vec.begin();
it = vec.insert(it, 200);
print_vec(vec);
vec.insert(it,2,300);
print_vec(vec);
// "it" no longer valid, get a new one:
it = vec.begin();
std::vector<int> vec2(2,400);
vec.insert(it+2, vec2.begin(), vec2.end());
print_vec(vec);
int arr[] = { 501,502,503 };
vec.insert(vec.begin(), arr, arr+3);
print_vec(vec);
}
- push_back,尾部插入
void push_back( const T& value );
#include <vector>
#include <iostream>
#include <iomanip>
int main()
{
std::vector<std::string> numbers;
numbers.push_back("abc");
std::string s = "def";
numbers.push_back(std::move(s));
std::cout << "vector holds: ";
for (auto&& i : numbers) std::cout << std::quoted(i) << ' ';
std::cout << "\nMoved-from string holds " << std::quoted(s) << '\n';
}
遍历
- 基于迭代器遍历
vector<string> first={"one","two","three","four"};
for(int i=0;i<first.size();i++)
cout<<first[i]<<" ";
- 基于for范围遍历
for(auto& i:first){
cout<<i<<" ";
}
访问
- 通过 [] 访问
vector<string> first={"one","two","three","four"};
cout<<first[0]<<endl;
- 通过at()访问
cout<<first.at(0)<<endl;
- front:返回第一个元素的引用
reference front();
const_reference front() const;
- back():返回最后一个元素的引用
reference back();
const_reference back() const;
获取vector中元素的地址
假设容器中至少有一个元素,则可以通过下面的方法获取容器的初始元素的地址。
std::vector<int> vec(3,100);
&vec[0]
//或者
&vec.front()
//或者
& *vec.begin()
在C ++ 11中,一个新的成员函数被添加到 std :: vector :data()。这个成员函数返回容器中初始元素的地址,等价于&vec.front()。这个成员函数的优点是即使容器是空的也可以调用它。
value_type* data() noexcept;
const value_type* data() const noexcept;
// vector::data
#include <iostream>
#include <vector>
int main ()
{
std::vector<int> myvector (5);
int* p = myvector.data();
*p = 10;
++p;
*p = 20;
p[2] = 100;
std::cout << "myvector contains:";
for (unsigned i=0; i<myvector.size(); ++i)
std::cout << ' ' << myvector[i];
std::cout << '\n';
return 0;
}
查找
vector没有提供用于查找的成员函数,所以需要用标准库中的算法来实现查找
参考:
https://www.cnblogs.com/Braveliu/p/13019377.html
- vector中的元素为内置数据类型
#include <iostream>
#include <vector>
#include <string>
// 为了便于示例,声明全局容器
std::vector<std::string> strVec;
void methods(const std::string& target)
{
// 方法一:遍历容器,查找相等元素判断是否存在
{
for (const auto& item : strVec)
{
if (item == target)
{
std::cout << "method1: find " << target << " exists." << std::endl;
break;
}
}
}
// 方法二:获取元素个数,通过个数判断是否存在
{
int nCount = std::count(strVec.begin(), strVec.end(), target);
if (nCount > 0)
{
std::cout << "method2: find " << target << " exists." << std::endl;
}
}
// 方法三:查询元素迭代器,通过迭代器有效性判断是否存在
{
auto iter = std::find(strVec.begin(), strVec.end(), target);
if (iter != strVec.end())
{
std::cout << "method3: find " << target << " exists." << std::endl;
}
}
// 方法四:查询相等元素的迭代器,通过迭代器有效性判断是否存在
{
auto iter = std::find_if(strVec.begin(), strVec.end(), [&](const std::string& item)->bool
{ return (item == target); });
if (iter != strVec.end())
{
std::cout << "method4: find " << target << " exists." << std::endl;
}
}
}
int main()
{
strVec = { "C", "C++", "Java", "Python", "Lua", "Sql" };
// 场景1:查找Ruby
std::cout << "Find Ruby" << std::endl;
methods("Ruby");
// 场景2:查找C++
std::cout << "Find C++" << std::endl;
methods("C++");
system("pause");
return 0;
}
// result
/*
Find Ruby
Find C++
method1: find C++ exists.
method2: find C++ exists.
method3: find C++ exists.
method4: find C++ exists.
*/
- vector中的元素为自定义数据类型
需要在类型中重载bool operator==()函数
#include <iostream>
#include <map>
#include <string>
#include <vector>
struct Student
{
std::string code; // 学号(唯一性标识)
int grade; // 年级
std::map<std::string, double> scores; // <科目,成绩>
bool operator==(const Student& obj) const
{
return obj.code == code; // 只要学号相同即可
}
};
// 为了便于示例,声明全局容器
std::vector<Student> vecStu;
void methods(const Student& target)
{
// 方法一:遍历容器,查找相等元素判断是否存在
{
for (const auto& item : vecStu)
{
if (item == target)
{
std::cout << "method1: find exists." << std::endl;
break;
}
}
}
// 方法二:获取元素个数,通过个数判断是否存在
{
int nCount = std::count(vecStu.begin(), vecStu.end(), target);
if (nCount > 0)
{
std::cout << "method2: find exists." << std::endl;
}
}
// 方法三:查询元素迭代器,通过迭代器有效性判断是否存在
{
auto iter = std::find(vecStu.begin(), vecStu.end(), target);
if (iter != vecStu.end())
{
std::cout << "method3: find exists." << std::endl;
}
}
// 方法四:查询相等元素的迭代器,通过迭代器有效性判断是否存在
{
if (std::find_if(vecStu.begin(), vecStu.end(), [&](const Student& obj)->bool
{ return (obj == target); }) != vecStu.end())
{
std::cout << "method4: find exists." << std::endl;
}
}
}
int main()
{
vecStu.push_back({ "080605109", 6, { {"English", 100}, {"China", 100} } });
vecStu.push_back({ "080605110", 7, { {"English", 99}, {"China", 70} } });
vecStu.push_back({ "080605111", 8, { {"English", 98}, {"China", 69} } });
vecStu.push_back({ "080605112", 6, { {"English", 97}, {"China", 68} } });
vecStu.push_back({ "080605113", 7, { {"English", 96}, {"China", 67} } });
Student obj = { "080605114", 8, { {"English", 95}, {"China", 66} } };
vecStu.push_back(obj);
// 场景1:查找学号为[0806005109]的学生,我们暂不关注成绩
std::cout << "Find code: 0806005108" << std::endl;
methods(Student{ "0806005108", {} });
// 场景2:查找学号为[0806005114]的学生,我们暂不关注成绩
std::cout << "Find code: 0806005114" << std::endl;
methods(obj);
// 场景3:不想通过学号,只想查找六年级,是否存在英语和语文全为满分的学生
auto iter = std::find_if(vecStu.begin(), vecStu.end(), [&](const Student& obj)->bool
{ return (obj.grade == 6 &&
obj.scores.find("English")->second == 100 &&
obj.scores.find("China")->second == 100); });
if (iter != vecStu.end())
{
std::cout << "method: find 100 exists." << std::endl;
}
return 0;
}
// result
/*
Find code: 0806005108
Find code: 0806005114
method1: find exists.
method2: find exists.
method3: find exists.
method4: find exists.
method: find 100 exists.
*/
删除
- erase:删除迭代器position位置的元素
iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);
//删除pos指向的元素
iterator erase( iterator pos );
//范围删除
iterator erase( iterator first, iterator last );
-
pop_back:删除尾部的一个元素
-
clear:清空vector元素,不能访问后面的数据,但没有释放空间
-
如果需要释放内存,可以使用swap函数,用法如下:
std::vector<T>().swap(X);//先构造匿名vector,然后交换
作用相当于:
{
std::vector<T> temp;//1.构造空的临时vector
temp.swap(X); //2.和X交换后,X为空
}
//临时变量离开作用域就调用析构函数释放内存。
其他
- resize:重置vector容器的容量
void resize( size_type count, T value = T() );
void resize( size_type count );
void resize( size_type count, const value_type& value );
resize()做的操作是直接修改了容量大小,让我不能访问后面的数据,而不是释放空间。重新指定大小后,后面有空间就浪费掉了(因为他们存在,但不能使用)
swap()可以解决这个问题
参考连接
vector<int>(v).swap(v); //v是容器名
也就是说通过该语句,可以将v中空闲的空间释放掉。
这条语句可以分为两个部分:
vector(v) 和 .swap(v) 两部分
第一部分vector(v)
这条语句,通过 拷贝构造函数 创建了一个 匿名对象 ,这个匿名对象拥有v的全部数据,但是,没有空闲的空间,也就是说,这个匿名对象的容量和存储的数据量是相等的。经过 vector(v) 创建出来的匿名对象是没有空闲空间的。
第二部分 .swap(v) 调用该匿名类的swap()方法,交换v与匿名类的内容,结果如下
最后,该行语句指向完毕,匿名类被析构,空间被释放。
最终结果就是,原容器中的空位被释放
resize使用示例
#include <iostream>
#include <vector>
int main()
{
std::vector<int> c = {1, 2, 3};
std::cout << "The vector holds: ";
for(auto& el: c) std::cout << el << ' ';
std::cout << '\n';
c.resize(5);
std::cout << "After resize up to 5: ";
for(auto& el: c) std::cout << el << ' ';
std::cout << '\n';
c.resize(2);
std::cout << "After resize down to 2: ";
for(auto& el: c) std::cout << el << ' ';
std::cout << '\n';
}
//Output:
//The vector holds: 1 2 3
//After resize up to 5: 1 2 3 0 0
//After resize down to 2: 1 2
二维vector
转到https://blog.csdn.net/qq_35987777/article/details/105905452