当前位置:首页 > 芯闻号 > 充电吧
[导读]const引用在C++语言中,引用是作为一种高效,安全的传递数据的方式而存在的。除了一般的引用类型,还可以声明const引用。我们有以下一个Image类。class Image { public:  

const引用


在C++语言中,引用是作为一种高效,安全的传递数据的方式而存在的。除了一般的引用类型,还可以声明const引用。


我们有以下一个Image类。


class Image
{
public:
    Image(int w, int h)
        :width(w), height(h)
    {
        data = new char[getSize()];
    }
    int getSize(){
        return width * height;
    } 
    virtual ~(){
       if(data != nullptr){
            delete data;
            data = nullptr;
            width = 0;
            height = 0;
        }
    }
private:
    int width = 0;
    int height = 0;
    char* data = nullptr;
}


上面只是这个类的雏形,只有构造函数,析构函数和取得数据大小的功能。


接下来添加比较两个Image是否相同的函数。最简单的形式大致如下。


bool isSame(Image& img)
{
    if(width == img.width
      && height == img.height){
        return (memcmp(data,img.data,getSize())==0);
    }
    else{
        return false;
    }
}


这里使用引用类型的参数,避免了没有必要的拷贝动作。当然我们还可以做得更好:由于比较函数没有必要也不应该对比较对象的内容进行修改,所以还可用下面的形式进行承诺:

bool isSame(const Image& img)
{
    if(width == img.width
      && height == img.height){
        char* in = static_cast

通过在参数前面增加const修饰符,向isSame方法的调用者保证,不会修改img的内容。


右值引用


继续添加将一个Image的一部分merge到另一个Image上的方法。函数的内容大致如下(这里忽略处理的细节):


void merge(Image& img){
    //接管img中的数据。
    img.height = 0;
    img.width = 0;
    img.data = nullptr;
}


类似的操作在处理在输入对象时一般有两种处理方式。有时希望只是参照而不破坏输入数据,这时可以使用前面讲到的为参数增加const修饰符的方式来承诺;有时为了提高效率或者其他的原因希望可以接管输入的数据,就像上面代码的状态。这时的行为更像是数据移动。


对于第二种方式,如果仅仅定义一般的引用类型,利用者根本没有办法通过方法声明来确定这个操作是否会接管参数中的数据。这种不确定性会造成很大的麻烦。


解决这个问题的方法就是今天文章的题目--右值引用。代码如下:

   

void merge(Image&& img){
    //接管img中的数据。
    img.height = 0;
    img.width = 0;
    img.data = nullptr;
}


我们将参数声明为右值引用,要求像一个临时变量一样任性地使用数据。使用这个函数的方法如下:


Image img1(100, 100);
Image img2(100, 200);
img1.merge(std::move(img2));


注意代码中的std::move,这是标准库中提供的方法,它可以将左值显式转换为右值引用类型,从而告诉编译器,可以像右值(临时变量)一样处理它。同时也意味着接下来除了对img2赋值或销毁以外,不再使用它。


C++11通过使用右值引用提供了一种接管数据的标准方法。


作者观点


如果说使用const修饰符可以对外承诺不对参数进行修改的话,那么使用右值引用就是对外要求接管参数数据的权利。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

c++程序员面试过程中基本上都会被问到c++11新特性吧,你是怎么回答的呢? 本文基本上涵盖了c++11的所有新特性,并有详细代码介绍其用法,对关键知识点做了深入分析,对重要的知识点我单独写了相关文章并附上了相关链接,我...

关键字: c++11

很多人谈到c++,说它特别难,可能有一部分就是因为c++的内存管理吧,不像java那样有虚拟机动态的管理内存,在程序运行过程中可能就会出现内存泄漏,然而这种问题其实都可以通过c++11引入的智能指针来解决,相反我还认为这...

关键字: c++11

c++11关于并发引入了好多好东西,这里按照如下顺序介绍: std::thread相关 std::mutex相关 std::lock相关 std::atomic相关 std::call_once相关 volatile相关...

关键字: 线程 c++11

以前,在lambda表达式没有进入标准的时候,对容器的遍历等涉及到使用函数指针的情况,一般人会懒得使用std::for_each,或std::transform,也许只是一个短短的几句话,却要单独写个

关键字: c++ c++11

C++11终于知道要在语言中加入匿名函数了。匿名函数在很多时候可以为编码提供便利,这在下文会提到。很多语言中的匿名函数,如C++,都是用Lambda表达式实现的。Lambda表达式又称为lambda函

关键字: c++11 lambda函数

emplace操作是C++11新特性,新引入的的三个成员emlace_front、empace 和 emplace_back,这些操作构造而不是拷贝元素到容器中,这些操作分别对应push_front、

关键字: c++11 emplace

左值和右值在C++表达式的特性中有一个左值和右值的概念。如果一个表达式可以放在赋值语句的左侧,就称之为左值,如果不能放到表达式的左侧,就称之为右值。不同的运算符对运算对象的要求各不相同,例如:赋值运算

关键字: c++ 右值引用

让我们从std::make_unique和std::make_shared之间的比较开始讲起吧。std::make_shared是C++11的一部分,可惜的是,std::make_unique不是,它

关键字: c++ c++11

为什么需要别名下面的说明只是一个例子,实际的使用场景一定不止这些。假设有一个二维图形计算的程序,定义了一个point结构体。struct point{   int x;   int y;};在有些系统

关键字: c++11 类型别名

熟悉C++98/03的对于for循环就再了解不过了,如果我们要遍历一个数组,那么在C++98/03中的实现方式:int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 1

关键字: c++ c++11
关闭
关闭