1.C++标准库中vector的operator[]和at()异同
- 两者都用于访问vector中的元素
- operator[] 不进行范围检查,at()在访问前进行范围检查
- operator[] 越界时不抛出(未定义的行为),但 at() 越界时抛出
- operator[]更快,at()更慢
#include <vector>
#include <iostream>
using namespace std;
int main()
{
vector vec = {1, 2, 4};
cout << vec.at(0)<<endl; // 1
cout << vec[0] << endl; // 1
cout << vec[5] << endl; // 0
// cout << vec.at(5) <<endl; // throw error
}
2.如何在 C++ 中的 main 之前调用一些函数?
- 方法一:
#include <iostream>
using namespace std;
void func(){cout << "inside func()" << endl;}
class Base{
public:
Base(){func();}
};
Base b;
int main()
{
cout << "inside main" << endl;
return 0;
}
// inside func()
// inside main
- 方法二:
#include <iostream>
using namespace std;
int func(){cout << "inside func()" << endl; return 100;}
class Base{
public:
static int staticVariant;
};
int Base::staticVariant = func();
int main()
{
cout << "inside main" << endl;
return 0;
}
// inside func()
// inside main
3.在C和C++中的结构填充和包装
#include <iostream>
using namespace std;
struct Base
{
};
int main()
{
cout << sizeof(Base) <<endl;
}
// 1
// 空结构体占用一个字节内存
#include <iostream>
using namespace std;
struct Base
{
char a;
char b;
};
int main()
{
cout << sizeof(Base) <<endl;
}
// 2
// 一个char占用一个字节内存
#include <iostream>
using namespace std;
struct Base
{
char a;
short b;
};
int main()
{
cout << sizeof(Base) <<endl;
cout << sizeof(short) << endl;
}
// 4
// 2
// 一个char占用一个字节内存, 一个short占用2个字节内存,但需要与short对齐
#include <iostream>
using namespace std;
struct Base
{
char a;
char b;
char c;
short d;
int e;
};
int main()
{
cout << sizeof(Base) <<endl;
cout << sizeof(short) << endl;
cout << sizeof(int) << endl;
}
// 12
// 2
// 4
// 一个char占用一个字节内存, 一个short占用2个字节内存,一个int占用2个字节内存,但需要对齐
#include <iostream>
using namespace std;
#pragma pack(1)
struct Base
{
char a;
char b;
char c;
short d;
int e;
};
int main()
{
cout << sizeof(Base) <<endl;
cout << sizeof(short) << endl;
cout << sizeof(int) << endl;
}
// 9
// 2
// 4
// 一个char占用一个字节内存, 一个short占用2个字节内存,一个int占用2个字节内存,结果与1(#pragma pack(1))对齐
#include <iostream>
using namespace std;
#pragma pack(2)
struct Base
{
char a;
char b;
char c;
short d;
int e;
};
int main()
{
cout << sizeof(Base) <<endl;
cout << sizeof(short) << endl;
cout << sizeof(int) << endl;
}
// 9
// 2
// 4
// 一个char占用一个字节内存, 一个short占用2个字节内存,一个int占用2个字节内存,结果与1(#pragma pack(2))对齐
#include <iostream>
using namespace std;
#pragma pack(2)
struct Base
{
char a;
char b;
char c;
short d;
char e;
short f;
int g;
};
int main()
{
cout << sizeof(Base) <<endl;
cout << sizeof(short) << endl;
cout << sizeof(int) << endl;
}
// 14
// 2
// 4
// 一个char占用一个字节内存, 一个short占用2个字节内存,一个int占用2个字节内存,结果与1(#pragma pack(2))对齐
4.C++中的显式构造函数
#include <iostream>
using namespace std;
class Base
{
private:
int b_var;
public:
Base(){}
Base(int var):b_var(var){}
void print(){cout<<b_var<<endl;}
};
void fun(Base b)
{
b.print();
}
int main()
{
Base obj1(10); // 对构造函数的普通调用
Base obj2 = 20; // 隐式调用构造函数
fun(obj1); // 对构造函数的普通调用
fun(30); // 隐式调用构造函数
return 0;
}
如果我们不想隐式调用,则如下操作:
#include <iostream>
using namespace std;
class Base
{
private:
int b_var;
public:
Base(){}
explicit Base(int var):b_var(var){}
void print(){cout<<b_var<<endl;}
};
void fun(Base b)
{
b.print();
}
int main()
{
Base obj1(10); // 对构造函数的普通调用
Base obj2 = 20; // 隐式调用构造函数 error
fun(obj1); // 对构造函数的普通调用
fun(30); // 隐式调用构造函数 error
return 0;
}
5.C++ 中的 const 成员函数
const成员函数表示不修改类的变量,如果在const成员函数中修改成员变量则会报错
#include <iostream>
using namespace std;
class Base
{
private:
int x;
int y;
public:
Base(){}
Base(int a, int b):x{a},y{b}{}
void setX(int a){ x = a;}
int getX() const { return x;}
// int getX() const { x= 30;return x;} //报错
};
int main()
{
Base b;
b.setX(10);
cout << b.getX() << endl;
}
此时,如果还是想在const成员函数中修改成员变量则需要如下操作:
#include <iostream>
using namespace std;
class Base
{
private:
mutable int x;
int y;
public:
Base(){}
Base(int a, int b):x{a},y{b}{}
void setX(int a){ x = a;}
int getX() const { x= 30;return x;}
};
int main()
{
Base b;
b.setX(10);
cout << b.getX() << endl;
}
6.std::copy和std::copy_if
以下代码使用 copy 将一个vector的内容复制到另一个vector并显示结果:
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <numeric>
int main()
{
std::vector<int> from_vector(10);
std::iota(from_vector.begin(), from_vector.end(), 0);
std::vector<int> to_vector;
std::copy(from_vector.begin(), from_vector.end(),
std::back_inserter(to_vector));
// 或者
// std::vector<int> to_vector(from_vector.size());
// std::copy(from_vector.begin(), from_vector.end(), to_vector.begin());
// 任何一种方式都相当于
// std::vector<int> to_vector = from_vector;
std::cout << "to_vector contains: ";
// 打印to_vector内容
std::copy(to_vector.begin(), to_vector.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
std::cout << "odd numbers in to_vector are: ";
std::copy_if(to_vector.begin(), to_vector.end(),
std::ostream_iterator<int>(std::cout, " "),
[](int x) { return x % 2 != 0; });
std::cout << '\n';
std::cout << "to_vector contains these multiples of 3:\n";
to_vector.clear();
std::copy_if(from_vector.begin(), from_vector.end(),
std::back_inserter(to_vector),
[](int x) { return x % 3 == 0; });
for (int x : to_vector)
std::cout << x << ' ';
std::cout << '\n';
}
/*
to_vector contains: 0 1 2 3 4 5 6 7 8 9
odd numbers in to_vector are: 1 3 5 7 9
to_vector contains these multiples of 3:
0 3 6 9
*/
7.对数据进行shuffle
以下代码随机打乱1~10整数 :
#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::random_device rd; // 是一个均匀分布的整数随机数生成器,该生成器产生不确定的随机数。
std::mt19937 g(rd()); //随机数引擎
std::shuffle(v.begin(), v.end(), g);
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
}
8.std::iota
以下示例将 std::shuffle 应用于 std::list 迭代器的向量,因为 std::shuffle 不能直接应用于 std::list。 std::iota 用于填充两个容器。
#include <algorithm>
#include <iostream>
#include <list>
#include <numeric>
#include <random>
#include <vector>
int main()
{
std::list<int> l(10);
std::iota(l.begin(), l.end(), -4);
std::vector<std::list<int>::iterator> v(l.size());
std::iota(v.begin(), v.end(), l.begin());
std::shuffle(v.begin(), v.end(), std::mt19937{std::random_device{}()});
std::cout << "Contents of the list: ";
for(auto n: l) std::cout << n << ' ';
std::cout << '\n';
std::cout << "Contents of the list, shuffled: ";
for(auto i: v) std::cout << *i << ' ';
std::cout << '\n';
}
/*
Contents of the list: -4 -3 -2 -1 0 1 2 3 4 5
Contents of the list, shuffled: 0 -1 3 4 -4 1 -2 -3 2 5
*/
9.静态成员变量和静态成员函数
#include <iostream>
using namespace std;
class Base
{
public:
int x;
static int y; // 静态成员变量属于整个类
void printX(){cout << x <<","<< y << endl;} //普通成员函数既可以访问静态成员变量又可以访问普通变量
static void printY(){cout << y << endl;} // 静态成员函数只能访问静态成员变量
};
int Base::y;
int main()
{
Base b1;
b1.x = 10;
Base::y = 30;
Base b2;
b2.x = 20;
Base::y = 40;
cout << b1.x << endl;
cout << b1.y << endl;
cout << b2.x << endl;
cout << b2.y << endl;
Base::printY();
b1.printX();
b1.printY();
b2.printX();
b2.printY();
/*
10
40
20
40
40
10,40
40
20,40
40
*/
}
10.C++中的浅拷贝与深拷贝
- 浅拷贝
#include <iostream>
using namespace std;
class Base
{
private:
int * _ptr;
int _val;
public:
Base():_ptr{new int(0)}, _val{0}{}
//Base(const Base& rhs)
//{
//_ptr = new int;
//*_ptr = *rhs._ptr;
//_val = rhs._val;
//}
void setPtr(int ptr){*_ptr=ptr;}
void setVal(int val){_val = val;}
int getPtr(){return *_ptr;}
int getVal(){return _val;}
};
int main()
{
Base b1;
b1.setPtr(10);
b1.setVal(15);
Base b2 = b1;
b2.setPtr(50);
cout << "b1 ptr: " << b1.getPtr()<<endl;
cout << "b1 val: "<< b1.getVal()<<endl;
cout << "b2 ptr: "<< b2.getPtr()<<endl;
cout << "b2 val: " << b2.getVal()<<endl;
/*
b1 ptr: 50
b1 val: 15
b2 ptr: 50
b2 val: 15
*/
}
- 深拷贝
#include <iostream>
using namespace std;
class Base
{
private:
int * _ptr;
int _val;
public:
Base():_ptr{new int(0)}, _val{0}{}
Base(const Base& rhs)
{
_ptr = new int;
*_ptr = *rhs._ptr;
_val = rhs._val;
}
void setPtr(int ptr){*_ptr=ptr;}
void setVal(int val){_val = val;}
int getPtr(){return *_ptr;}
int getVal(){return _val;}
};
int main()
{
Base b1;
b1.setPtr(10);
b1.setVal(15);
Base b2 = b1;
b2.setPtr(50);
cout << "b1 ptr: " << b1.getPtr()<<endl;
cout << "b1 val: "<< b1.getVal()<<endl;
cout << "b2 ptr: "<< b2.getPtr()<<endl;
cout << "b2 val: " << b2.getVal()<<endl;
/*
b1 ptr: 10
b1 val: 15
b2 ptr: 50
b2 val: 15
*/
}