我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++11右值引用和移动语义的方法是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++11右值引用和移动语义的方法是什么

本文小编为大家详细介绍“C++11右值引用和移动语义的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++11右值引用和移动语义的方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

    左值引用与右值引用

    1、左值与右值

    概念1:

    • 左值:可以放到等号左边的东西叫左值。

    • 右值:不可以放到等号左边的东西就叫右值。

    概念2

    • 左值:可以取地址并且有名字的东西就是左值。

    • 右值:不能取地址的没有名字的东西就是右值。

    概念3

    • 左值是指那些在表达式执行结束后依然存在的数据,也就是持久性的数据。

    • 右值是指那些在表达式执行结束后不再存在的数据,也就是临时性的数据。

    有一种很简单的方法来区分左值和右值:对表达式取地址,如果编译器不报错就为左值,否则为右值。例如:int a = b + c;,a 是左值,有变量名,可以取地址,也可以放到等号左边,表达式 b+c 的返回值是右值,没有名字且不能取地址,&(b+c) 不能通过编译,而且也不能放到等号左边。

    左值一般有:

    • 变量名和函数名(注意:是函数名不是函数调用)

    • 返回左值引用的函数调用

    • 前置自增自减表达式++i、–i

    • 由赋值表达式或赋值运算符连接的表达式(a=b, a += b等)

    • 解引用表达式 *p

    • 字符串字面值 “abcd”

    2、纯右值、将亡值

    纯右值和将亡值都属于右值。

    纯右值:运算表达式产生的临时变量、不和对象关联的原始字面量、非引用返回的临时变量、lambda 表达式等都是纯右值。举例:

    • 除字符串字面值外的字面值

    • 返回非引用类型的函数调用

    • 后置自增自减表达式 i++、i–

    • 算术表达式 a+b,a*b,a&&b,a==b 等

    • 取地址表达式等,&a

    将亡值:

    将亡值是指 c++11 新增的和右值引用相关的表达式,通常指将要被移动的对象、T&& 函数的返回值、std::move函数的返回值、转换为 T&& 类型转换函数的返回值,将亡值可以理解为即将要销毁的值,通过“盗取”其它变量内存空间方式获取的值,在确保其它变量不再被使用或者即将被销毁时,可以避免内存空间的释放和分配,延长变量值的生命周期,常用来完成移动构造或者移动赋值的特殊任务。举例:

    class A {    xxx;};A a;auto c = std::move(a);         // c是将亡值auto d = static_cast<A&&>(a);  // d是将亡值

    3、左值引用与右值引用

    左值引用就是对左值进行引用的类型,右值引用就是对右值进行引用的类型,他们都是引用,都是对象的一个别名,并不拥有所绑定对象的堆存,所以都必须立即初始化。引用可以通过引用修改变量的值,传参时传引用可以避免拷贝。

    type &name = exp;  // 左值引用type &&name = exp; // 右值引用

    左值引用

    左值引用:能指向左值,不能指向右值的就是左值引用:

    int a = 5;int& b = a;  // b是左值引用b = 4;int& c = 10;  // error,10无法取地址,无法进行引用const int& d = 10;  // ok,因为是常引用,引用常量数字,这个常量数字会存储在内存中,可以取地址。

    引用是变量的别名,由于右值没有地址,没法被修改,所以左值引用无法指向右值,等号右边的值必须可以取地址,如果不能取地址,则会编译失败。

    但是,const 左值引用(常量引用)是可以指向右值的:const 左值引用不会修改指向值,因此可以指向右值,这也是为什么要使用 const & 作为函数参数的原因之一。

    右值引用

    c++11 标准新引入了另一种引用方式,称为右值引用,用 “&&” 表示。如果使用右值引用,那表达式等号右边的值需要是右值(不能是左值),可以使用 std::move 函数强制把左值转换为右值。

    int a = 4;int&& b = a;             // error, a 是左值int&& c = std::move(a);  // okint num = 10;int && a = num;         //error, 右值引用不能初始化为左值int && a = 10;          // ok

    【注意】和声明左值引用一样,右值引用也必须立即进行初始化操作。

    左值引用与右值引用本质

    (1)右值引用指向左值

    int a = 5; // a是个左值int &ref_a_left = a; // 左值引用指向左值int &&ref_a_right = std::move(a); // 通过std::move将左值转化为右值,可以被右值引用指向cout << a; // 打印结果:5

    前面讲过可以使用 std::move 函数强制把左值转换为右值,实现右值引用指向左值。std::move 是一个非常有迷惑性的函数:

    • 不理解左右值概念的人们往往以为它能把一个变量里的内容移动到另一个变量,比如在上边的代码里,看上去是左值 a 通过 std::move 移动到了右值 ref_a_right 中,那是不是a里边就没有值了?并不是,打印出a的值仍然是5。

    • 事实上 std::move 移动不了什么,唯一的功能是把左值强制转化为右值,让右值引用可以指向左值。其实现等同于一个类型转换: static_cast<T&&>(lvalue)。 所以,单纯的 std::move(xxx) 不会有性能提升。

    同样的,右值引用能指向右值,本质上也是把右值提升为一个左值,并定义一个右值引用通过 std::move:

    int &&ref_a = 5;ref_a = 6;// 等同于以下代码:int temp = 5;int &&ref_a = std::move(temp);ref_a = 6;

    (2)左值引用、右值引用本身是左值还是右值?

    被声明出来的左、右值引用都是左值。 因为被声明出的左右值引用是有地址的,也位于等号左边。仔细看下边代码:

    // 形参是个右值引用void change(int &&right_value) { right_value = 8; }int main() {    int a = 5;                         // a是个左值    int &ref_a_left = a;               // ref_a_left是个左值引用    int &&ref_a_right = std::move(a);  // ref_a_right是个右值引用    change(a);                         // 编译不过,a是左值,change参数要求右值    change(ref_a_left);                // 编译不过,左值引用ref_a_left本身也是个左值    change(ref_a_right);             // 编译不过,右值引用ref_a_right本身也是个左值    change(std::move(a));            // 编译通过    change(std::move(ref_a_right));  // 编译通过    change(std::move(ref_a_left));   // 编译通过    change(5);                       // 当然可以直接接右值,编译通过    cout << &a << ' ';    cout << &ref_a_left << ' ';    cout << &ref_a_right;    // 打印这三个左值的地址,都是一样的}

    看完后你可能有个问题,std::move 会返回一个右值引用 int && ,它是左值还是右值呢? 从表达式 int &&ref = std::move(a) 来看,右值引用 ref 指向的必须是右值,所以move返回的 int && 是个右值。所以右值引用既可能是左值,又可能是右值吗? 确实如此:右值引用既可以是左值也可以是右值,如果有名称则为左值,否则是右值。

    或者说:作为函数返回值的 && 是右值,直接声明出来的 && 是左值。 这同样也符合前面章节对左值,右值的判定方式:其实引用和普通变量是一样的, int &&ref = std::move(a) 和 int a = 5 没有什么区别,等号左边就是左值,右边就是右值。

    (3)无论是左值引用还是右值引用都是引用

    int temp = 5;int &ref_t = temp;int &&ref_a = std::move(temp);ref_a = 6;cout << &temp << "," << &ref_t << "," << &ref_a<<endl;cout << "temp:" <<temp <<endl;// 输出结果// 0x61fe84  0x61fe84  0x61fe84 // temp:6

    最后,从上述分析中我们得到如下结论:

    • 从性能上讲,左右值引用没有区别,传参使用左右值引用都可以避免拷贝。

    • 右值引用可以直接指向右值,也可以通过 std::move 指向左值;而左值引用只能指向左值(const左值引用也能指向右值)。

    • 作为函数形参时,右值引用更灵活。虽然 const 左值引用也可以做到左右值都接受,但它无法修改,有一定局限性。

    void f(const int& n) {    n += 1;  // 编译失败,const左值引用不能修改指向变量}void f2(int&& n) {    n += 1;  // ok}int main() {    f(5);    f2(5);}

    4、右值引用和 std::move 使用场景

    std::move 只是类型转换工具,不会对性能有好处;右值引用在作为函数形参时更具灵活性。他们有什么实际应用场景吗?

    1、右值引用优化性能,避免深拷贝

    (1)浅拷贝重复释放:对于含有堆内存的类,我们需要提供深拷贝的拷贝构造函数,如果使用默认构造函数,会导致堆内存的重复删除,比如下面的代码:

    class A {public:    A(int size) : size_(size) { data_ = new int[size]; }    A() {}    A(const A& a) {        size_ = a.size_;        data_ = a.data_;        cout << "copy " << endl;    }    ~A() { delete[] data_; }        int* data_;    int size_;};int main() {    A a(10);    A b = a;    cout << "b " << b.data_ << endl;    cout << "a " << a.data_ << endl;    return 0;}

    上面代码中,两个输出的是相同的地址,a 和 b 的 data_ 指针指向了同一块内存,这就是浅拷贝,只是数据的简单赋值,那再析构时 data_ 内存会被释放两次,导致程序出问题,这里正常会出现 double free 导致程序崩溃的。

    (2)深拷贝构造函数

    在上面的代码中,默认构造函数是浅拷贝,在析构的时候会导致重复删除指针。正确的做法是提供深拷贝的拷贝构造函数,比如下面的代码:

    #include <iostream>using namespace std;class A {public:    A() : m_ptr(new int(0)) { cout << "constructor A" << endl; }    A(const A& a) : m_ptr(new int(*a.m_ptr)) {        cout << "copy constructor A" << endl;    }    ~A() {        cout << "destructor A, m_ptr:" << m_ptr << endl;        delete m_ptr;        m_ptr = nullptr;    }private:    int* m_ptr;};// 为了避免返回值优化,此函数故意这样写A Get(bool flag) {    A a;    A b;    cout << "ready return" << endl;    if (flag)        return a;    else        return b;}int main() {    {        A a = Get(false);  // 正确运行    }    cout << "main finish" << endl;    return 0;}

    深拷贝就是在拷贝对象时,如果被拷贝对象内部还有指针引用指向其它资源,自己需要重新开辟一块新内存存储资源,而不是简单的赋值。虽然深拷贝可以解决浅拷贝的问题,但是存在效率问题。

    (3)移动构造函数

    深拷贝构造函数可以保证拷贝构造时的安全性,但有时这种拷贝构造存在效率问题,比如上面代码中的拷贝构造就是不必要的。上面代码中的 Get 函数会返回临时变量,然后通过这个临时变量拷贝构造了一个新的对象 b,临时变量在拷贝构造完成之后就销毁了,如果堆内存很大,那么,这个拷贝构造的代价会很大,带来了额外的性能损耗。

    有没有办法避免临时对象的拷贝构造呢?答案是肯定的。看下面的代码:

    #include <iostream>using namespace std;class A {public:    A() : m_ptr(new int(0)) { cout << "constructor A" << endl; }    A(const A& a) : m_ptr(new int(*a.m_ptr)) {        cout << "copy constructor A" << endl;    }    // 移动构造函数,可以浅拷贝    A(A&& a) : m_ptr(a.m_ptr) {        a.m_ptr = nullptr;  // 为防止a析构时delete data,提前置空其m_ptr        cout << "move constructor A" << endl;    }    ~A() {        cout << "destructor A, m_ptr:" << m_ptr << endl;        if (m_ptr) delete m_ptr;    }private:    int* m_ptr;};// 为了避免返回值优化,此函数故意这样写A Get(bool flag) {    A a;    A b;    cout << "ready return" << endl;    if (flag)        return a;      else        return b;}int main() {    {        A a = Get(false);  // 返回右值,调用移动构造函数    }    cout << "main finish" << endl;    return 0;}

    上面的代码中实现了移动构造( Move Construct)。从移动构造函数的实现中可以看到,它的参数是一个右值引用类型的参数 A&&,这里没有深拷贝,只有浅拷贝,这样就避免了对临时对象的深拷贝,提高了性能。

    在实际开发中,通常在类中自定义移动构造函数的同时,会再为其自定义一个适当的拷贝构造函数,由此当用户利用右值初始化类对象时,会调用移动构造函数;使用左值(非右值)初始化类对象时,会调用拷贝构造函数。

    这里的 A&& 用来根据参数是左值还是右值来建立分支,如果是临时值,则会选择移动构造函数。

    移动构造函数只是将临时对象的资源做了浅拷贝,不需要对其进行深拷贝,从而避免了额外的拷贝,提高性能。这也就是所谓的移动语义( move 语义),右值引用的一个重要目的是用来支持移动语义的(移动语义的分析详细见下文)。

    引用限定符

    将左值的类对象称为左值对象,将右值的类对象称为右值对象。默认情况下,对于类中用 public 修饰的成员函数,既可以被左值对象调用,也可以被右值对象调用,举个例子:

    #include <iostream>using namespace std;class demo {public:    demo(int num) : num(num) {}    int get_num() { return this->num; }private:    int num;};int main() {    demo a(10);    cout << a.get_num() << endl;    cout << move(a).get_num() << endl;    return 0;}

    可以看到,demo 类中的 get_num() 成员函数既可以被 a 左值对象调用,也可以被 move(a) 生成的右值 demo 对象调用,运行程序会输出两个 10。

    某些场景中,我们可能需要限制调用成员函数的对象的类型(左值还是右值),为此 c++11 新添加了引用限定符。所谓引用限定符,就是在成员函数的后面添加 “&” 或者 “&&”,从而限制调用者的类型(左值还是右值)。【注意】引用限定符不适用于静态成员函数和友元函数。

    // 代码修改class demo {public:    demo(int num) : num(num) {}    int get_num() & { return this->num; }  // 添加了 "&",限定调用该函数的对象必须是左值对象private:    int num;};int main() {    demo a(10);    cout << a.get_num() << endl;  // 正确    // cout << move(a).get_num() << endl;  // 错误    return 0;}
    // 代码修改class demo {public:    demo(int num) : num(num) {}    int get_num() && { return this->num; }  // 添加了 "&&",限定调用该函数的对象必须是右值对象private:    int num;};int main() {    demo a(10);    //cout << a.get_num() << endl; // 错误    cout << move(a).get_num() << endl; // 正确    return 0;}

    const 和引用限定符

    const 也可以用于修饰类的成员函数,习惯称为常成员函数。

    const 和引用限定符修饰类的成员函数时,都位于函数的末尾。C++11 标准规定,当引用限定符和 const 修饰同一个类的成员函数时,const 必须位于引用限定符前面。如下:

    #include <iostream>using namespace std;class demo {public:    demo(int num, int num2) : num(num), num2(num2) {}    //左值和右值对象都可以调用    int get_num() const& { return this->num; }    //仅供右值对象调用    int get_num2() const&& { return this->num2; }private:    int num;    int num2;};

    【注意】当 const && 修饰类的成员函数时,调用它的对象只能是右值对象;当 const & 修饰类的成员函数时,调用它的对象既可以是左值对象,也可以是右值对象。无论是 const && 还是 const & 限定的成员函数,内部都不允许对当前对象做修改操作。

    移动语义&mdash;std::move()

    所谓移动语义,指的就是以移动而非深拷贝的方式初始化含有指针成员的类对象:之前的拷贝是对于别人的资源,自己重新分配一块内存存储复制过来的资源,而对于移动语义,类似于转让或者资源窃取的意思,对于那块资源,转为自己所拥有,别人不再拥有也不会再使用,通过 c++11 新增的移动语义可以省去很多拷贝负担,怎么利用移动语义呢,是通过移动构造函数。

    移动语义可以将资源(堆、系统对象等)通过浅拷贝方式从一个对象转移到另一个对象,这样能够减少不必要的临时对象的创建、拷贝以及销毁,可以大幅度提高 c++ 应用程序的性能,消除临时对象的维护(创建和销毁)对性能的影响。

    class A {public:    A(int size) : size_(size) { data_ = new int[size]; }    A() {}    A(const A& a) {        size_ = a.size_;        data_ = new int[size_];        cout << "copy " << endl;    }    A(A&& a) {                       // 移动构造函数        this->data_ = a.data_;        a.data_ = nullptr;        cout << "move " << endl;    }    ~A() {        if (data_ != nullptr) {            delete[] data_;        }    }    int* data_;    int size_;};int main() {    A a(10);    A b = a;    A c = std::move(a);  // 返回右值,调用移动构造函数    return 0;}

    如果不使用 std::move(),会有很大的拷贝代价,使用移动语义可以避免很多无用的拷贝,提供程序性能,c++ 所有的 STL 都实现了移动语义,方便我们使用。

    【注意1】移动语义仅针对于那些实现了移动构造函数的类的对象,对于那种基本类型 int、float 等没有任何优化作用,还是会拷贝,因为它们实现没有对应的移动构造函数。

    【注意2】在实际开发中,通常在类中自定义移动构造函数的同时,会再为其自定义一个适当的拷贝构造函数,由此当用户利用右值初始化类对象时,会调用移动构造函数;使用左值(非右值)初始化类对象时,会调用拷贝构造函数。

    完美转发

    首先,解释一下什么是完美转发,它指的是函数模板可以将自己的参数“完美”地转发给内部调用的其它函数。所谓完美,即不仅能准确地转发参数的值,还能保证被转发参数的左、右值属性不变。例如:

    template <typename T>void function(T t) {    otherdef(t);}

    如上所示,function() 函数模板中调用了 otherdef() 函数。在此基础上,完美转发指的是:如果 function() 函数接收到的参数 t 为左值,那么该函数传递给 otherdef() 的参数 t 也是左值;反之如果 function() 函数接收到的参数 t 为右值,那么传递给 otherdef() 函数的参数 t 也必须为右值。

    显然, function() 函数模板并没有实现完美转发。一方面,参数 t 为非引用类型,这意味着在调用 function() 函数时,实参将值传递给形参的过程就需要额外进行一次拷贝操作;另一方面,无论调用 function() 函数模板时传递给参数 t 的是左值还是右值,对于函数内部的参数 t 来说,它有自己的名称,也可以获取它的存储地址,因此它永远都是左值,也就是说,传递给 otherdef() 函数的参数 t 永远都是左值。总之,无论从那个角度看, function() 函数的定义都不“完美”。

    接下来,那如何实现完美转发呢,答案是使用 std::forward():

    • 首先在定义模板函数时,采用右值引用的语法格式定义参数类型,由此该函数既可以接收外界传入的左值,也可以接收右值;

    • 其次,还需要使用 c++11 标准库提供的 std::forword() 模板函数修饰被调用函数中需要维持左、右值属性的参数。

    由此即可轻松实现函数模板中参数的完美转发,如下所示:

    void PrintV(int& t) { cout << "lvalue" << endl; }void PrintV(int&& t) { cout << "rvalue" << endl;}template <typename T>void Test(T&& t) {               // 1、采用右值引用的语法格式定义参数类型    PrintV(t);    PrintV(std::forward<T>(t));    PrintV(std::move(t));}int main() {    Test(1);                       // lvalue rvalue rvalue    int a = 1;    Test(a);                       // lvalue lvalue rvalue    // 2、使用 std::forword() 模板函数修饰被调用函数    Test(std::forward<int>(a));    // lvalue rvalue rvalue    Test(std::forward<int&>(a));   // lvalue lvalue rvalue    Test(std::forward<int&&>(a));  // lvalue rvalue rvalue    return 0;}
    • Test(1):1是右值,模板中 T &&t 这种为万能引用,右值 1 传到 Test 函数中变成了右值引用,但是调用 PrintV() 时候,t 变成了左值,因为它变成了一个拥有名字的变量,所以打印 lvalue,而 PrintV(std::forward<T>(t)) 时候,会进行完美转发,按照原来的类型转发,所以打印 rvalue,PrintV(std::move(t)) 毫无疑问会打印 rvalue。

    • Test(a):a 是左值,模板中 T && 这种为万能引用,左值 a 传到 Test 函数中变成了左值引用,所以有代码中打印。

    • Test(std::forward<T>(a)):转发为左值还是右值,依赖于 T,T 是左值那就转发为左值,T 是右值那就转发为右值。

    #include <iostream>using namespace std;//重载被调用函数,查看完美转发的效果void otherdef(int & t) {    cout << "lvalue\n";}void otherdef(const int & t) {    cout << "rvalue\n";}//实现完美转发的函数模板template <typename T>void function(T&& t) {    otherdef(forward<T>(t));}int main(){    function(5);  // rvalue    int  x = 1;    function(x);  // lvalue    return 0;}// 打印结果// rvalue  // lvalue

    emplace_back 减少内存拷贝和移动

    对于STL容器,c++11 后引入了 emplace_back 接口。emplace_back 是就地构造,不用构造后再次复制到容器中,因此效率更高。考虑这样的语句:

    vector<string> testVec;testVec.push_back(string(16, 'a'));

    上述语句足够简单易懂,将一个 string 对象添加到 testVec 中。底层实现:

    • 首先,string(16, &lsquo;a&rsquo;) 会创建一个 strin g类型的临时对象,这涉及到一次string 构造过程。

    • 其次,vector 内会创建一个新的 string 对象,这是第二次构造。

    • 最后在 push_back 结束时,最开始的临时对象会被析构。加在一起,这两行代码会涉及到两次 string 构造和一次析构。

    c++11 可以用 emplace_back 代替 push_back,emplace_back 可以直接在vector中构建一个对象,而非创建一个临时对象,再放进vector,再销毁。emplace_back可以省略一次构建和一次析构,从而达到优化的目的。

    emplace_back 内部没有使用拷贝构造函数,也没有使用移动构造函数,而是直接调用构造函数,因此更加高效。

    读到这里,这篇“C++11右值引用和移动语义的方法是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    C++11右值引用和移动语义的方法是什么

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    C++11右值引用和移动语义的方法是什么

    本文小编为大家详细介绍“C++11右值引用和移动语义的方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++11右值引用和移动语义的方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。左值引用与右值
    2023-07-05

    C++中右值引用与移动语义的方法是什么

    今天小编给大家分享一下C++中右值引用与移动语义的方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。意义充分利用临时对
    2023-07-05

    C++11学习之右值引用和移动语义详解

    c++11中引用了右值引用和移动语义,可以避免无谓的复制,提高了程序性能。这篇文章将通过一些示例和大家聊聊右值引用和移动语义的使用,感兴趣的可以了解一下
    2023-02-23

    C++11右值引用方法是什么

    本篇内容介绍了“C++11右值引用方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!左值和右值在C++表达式的特性中有一个左值和右值的
    2023-06-19

    C++11语法之右值引用的方法

    这篇文章主要讲解了“C++11语法之右值引用的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++11语法之右值引用的方法”吧!一、{}的扩展在原先c++的基础上,C++11扩展了很多初
    2023-06-29

    C++右值引用,移动语义与完美转发得方法

    本篇内容主要讲解“C++右值引用,移动语义与完美转发得方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++右值引用,移动语义与完美转发得方法”吧!C++——左值与右值
    2023-06-29

    C++11万能引用和右值引用的方法

    这篇文章主要介绍了C++11万能引用和右值引用的方法的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++11万能引用和右值引用的方法文章都会有所收获,下面我们一起来看看吧。正文实际上,type&& 有两种不同的
    2023-06-29

    C++右值引用与移动构造函数应用的方法是什么

    这篇文章主要讲解了“C++右值引用与移动构造函数应用的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++右值引用与移动构造函数应用的方法是什么”吧!1.右值引用右值引用是 C++
    2023-07-05

    一文带你了解C++中的右值引用与移动语义

    本篇文章主要为大家详细介绍了C++中的右值引用与移动语义的相关知识,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2023-05-13

    C++中左值与右值的概念与应用方法是什么

    这篇文章主要讲解了“C++中左值与右值的概念与应用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++中左值与右值的概念与应用方法是什么”吧!什么是左值与右值?左值(Lvalue)
    2023-07-05

    C语言宏的定义与使用方法是什么

    本文小编为大家详细介绍“C语言宏的定义与使用方法是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言宏的定义与使用方法是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、C语言中的宏定义#define
    2023-06-30

    c语言转义字符的使用方法是什么

    在C语言中,转义字符以反斜杠(\)开头,用于表示一些特殊字符或控制字符,例如换行符(\n)、制表符(\t)、回车符(\r)、退格符(\b)等。转义字符的使用方法是在需要输入特殊字符时,在字符前加上反斜杠即可。例如,要在字符串中输出换行符,可
    c语言转义字符的使用方法是什么
    2024-03-01

    c语言函数的定义与调用方法是什么

    C语言函数的定义和调用方法如下:1. 函数的定义:在C语言中,函数的定义包括函数的返回类型、函数名、参数列表和函数体。函数的定义一般写在main函数之前或者使用函数原型声明。函数定义的一般形式如下:返回类型 函数名(参数列表) {函数体}例
    2023-08-18

    c语言多维数组初始化和赋值的方法是什么

    在C语言中,多维数组的初始化和赋值可以使用以下方法:静态初始化:在定义数组时,直接给出各个元素的初始值。int arr[3][2] = {{1, 2}, {3, 4}, {5, 6}};动态初始化:在定义数组后,使用循环遍历的方式给各个元
    2023-10-23

    C++调用动态库和Python调用C++动态库的方法是什么

    这篇文章主要介绍“C++调用动态库和Python调用C++动态库的方法是什么”,在日常操作中,相信很多人在C++调用动态库和Python调用C++动态库的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答
    2023-07-05

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录