C++基础知识(八)

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
	*/
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值