c++11

文章目录

c++11基础知识点

初始化,一切皆可{}初始化,并且可以不加=符号

bash 复制代码
#include <iostream>
using namespace std;

class Point
{
public:
    Point(int x, int y)
        : _x(x), _y(y)
    {
        cout << "构造函数" << endl;
    }

    ~Point()
    {
    }

private:
    int _x;
    int _y;
};

int main()
{
    int x = 1;
    int y = {1};
    int z{1};

    int a1[] = {1, 2, 3, 4, 5};
    int a2[]{1, 2, 3, 4, 5};

    Point n1(1, 1);
    Point n2 = {1, 1}; //多参数的隐式类型转换 加explicit就不能转换了
    Point n3{2, 2};

    int *ptr1 = new int[3]{1, 2, 3};
    Point *n4 = new Point[2]{{1, 1}, {2, 2}};
    return 0;
}
复制代码

initializer_list容器

c 复制代码
//c++11中 {10,20,30}这是一个常量数组,被放在常量区

template <class T>
class initializer_list
{
	const T* _start;
    const T* _finish;
}
//这两个指针分别指向常量区的首部,和最后一个元素的下一个位置。


vector<int> v1 = {1,2,3,4,5}  //这后面的列表也是一个initialzer_list,vector的构造函数实现了参数是initalizer_list类型的构造

//vector内部其实是这样实现构造的
vector(initializer_list<value_type> il)
{
    reserve(il.size());
    for(auto& e:il)
    {
        push_back(e);
    }
}

decltype

c 复制代码
int i = 1;
auto f = &i;
auto pf = malloc;

cout<<typeid(f).name()<<endl;
cout<<typeid(pf).namej()<<endl;

decltype(pf) pf2;

//typeid推出类型只是一个字符串,只能看不能用
//decltype退出对象的类型,可以定义变量,后者作为模板实参

array

对标的是静态数组,指针解引用,数组越界的情况。

c 复制代码
int mian()
{
    int a[10] = {1,2,3,4,5,6,7,8,9,10};
   	array<int,10> aty = {1,2,3,4,5,6};
    a[15] = 1; //指针的解引用
    aty[15] = 2; //operator[] 函数的调用,内部检查
    return 0; 
}

forward_list

就是一个单链表,单项迭代器

可变模板参数

原理

c 复制代码
template<class T> 
void ShowList(T value)
{
    //结束条件的函数
	cout << value << endl;
}
template <class T,class ...Args>
void ShowList(T value, Args... args)
{
	cout << value << endl;
	ShowList(args...);
}

使用的是编译时递归,而不是采用c语言的方式,并没有把每一个参数都存储起来。

实际用途

c 复制代码
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_month(month)
		, _year(year)
		, _day(day)
	{

	}
private:
	int _month;
	int _year;
	int _day;
};
template<class ...Args>
Date* Create(Args... args)
{
	Date* ret = new Date(args...);

	return ret;
}
int main()
{
	Date* A = Create(2001,11,4);
	Date* B = Create(A);//甚至传递类也是可以的,调用的是拷贝构造
	return 0;
}

emplace

原理:

c 复制代码
int main()
{
    std::list<std::pair<int,string>> mylist;
    mylist.emplace_back(10,"soct");//这里底层调用的是构造函数
    mylist.emplace_back(make_pair(10,"sock"));//这里底层用的是拷贝构造。
    
    mylist.push_back(make_pair(30,"sort"));//这里是移动构造
    mylist.push_back({40,"sort"}); //这里是移动构造 
    return 0;
}

可以接受参数包用于原地构造对象,也可以接受已经构造好的对象。

参数包:

emplace 系列接口使用了可变参数模板(variadic templates),因此你可以直接传递多个参数来调用对象的构造函数,这允许你直接在容器的内存中构造对象,而不需要先创建临时对象。

已经构造好的对象:

即使你传递的是一个已经构造好的对象,emplace 系列接口仍然会尽可能避免不必要的拷贝或移动操作。具体来说,传递一个对象时,emplace 会利用移动构造函数(如果有),否则会使用拷贝构造函数。

示例:

传递参数包:
cpp 复制代码
#include <iostream>
#include <vector>

class MyClass {
public:
    MyClass(int x, double y) {
        std::cout << "Constructor called with x = " << x << ", y = " << y << std::endl;
    }
};

int main() {
    std::vector<MyClass> vec;
    
    // 使用 emplace_back 传递参数包构造对象
    vec.emplace_back(10, 20.5);  // 直接调用 MyClass(int, double) 构造函数
    
    return 0;
}

输出

Constructor called with x = 10, y = 20.5
传递对象:
cpp 复制代码
#include <iostream>
#include <vector>

class MyClass {
public:
    MyClass(int x, double y) {
        std::cout << "Constructor called with x = " << x << ", y = " << y << std::endl;
    }

    MyClass(const MyClass& other) {
        std::cout << "Copy constructor called" << std::endl;
    }

    MyClass(MyClass&& other) noexcept {
        std::cout << "Move constructor called" << std::endl;
    }
};

int main() {
    std::vector<MyClass> vec;

    MyClass obj(30, 40.5);  // 创建一个对象

    // 使用 emplace_back 传递已经构造好的对象
    vec.emplace_back(obj);  // 这里会调用拷贝构造函数
    vec.emplace_back(std::move(obj));  // 这里会调用移动构造函数
    
    return 0;
}

输出

Constructor called with x = 30, y = 40.5
Copy constructor called
Move constructor called

总结:

  • 参数包emplace 系列接口可以传递多个参数,这些参数会被传递给对象的构造函数以在容器中直接构造对象,避免了构造临时对象然后移动或拷贝的开销。
  • 传递对象 :如果你传递一个已经构造好的对象,emplace 会尽量调用移动构造函数(如果对象是通过 std::move 传递的),否则调用拷贝构造函数。

emplace 系列接口的优势在于它可以灵活处理不同类型的参数传递方式,从而减少性能损耗,尤其是避免了不必要的拷贝或移动操作。

相关推荐
诚丞成5 分钟前
计算世界之安生:C++继承的文水和智慧(上)
开发语言·c++
Smile灬凉城66617 分钟前
反序列化为啥可以利用加号绕过php正则匹配
开发语言·php
lsx20240628 分钟前
SQL MID()
开发语言
Dream_Snowar32 分钟前
速通Python 第四节——函数
开发语言·python·算法
西猫雷婶33 分钟前
python学opencv|读取图像(十四)BGR图像和HSV图像通道拆分
开发语言·python·opencv
鸿蒙自习室34 分钟前
鸿蒙UI开发——组件滤镜效果
开发语言·前端·javascript
言、雲41 分钟前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
东风吹柳1 小时前
观察者模式(sigslot in C++)
c++·观察者模式·信号槽·sigslot
A懿轩A1 小时前
C/C++ 数据结构与算法【栈和队列】 栈+队列详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·栈和队列
汪洪墩1 小时前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium