什么是复制省略以及它如何优化副本

我正在阅读复制和交换。

我尝试阅读Copy Elision上的一些链接,但无法正确理解它的含义。 有人可以解释一下这个优化是什么,特别是下面的文字是什么意思

这不仅仅是方便的问题,实际上是一种优化。 如果参数绑定到一个左值(另一个非const对象),则在创建参数时会自动创建该对象的副本。 但是,当s绑定到右值(临时对象,文字)时,副本通常会被省略,这会保存对复制构造函数和析构函数的调用。 在参数被接受为常量引用的赋值运算符的早期版本中,当引用绑定到右值时,复制elision不会发生。 这导致一个额外的对象被创建和销毁。


复制构造函数用于复制。 在理论上,当你写一行如下:

CLASS c(foo());

编译器将不得不调用复制构造函数将foo()的返回值复制到c

复制elision是一种跳过调用复制构造函数的技巧,以免支付开销。

例如,编译器可以安排foo()将直接构造它的返回值到c

这是另一个例子。 假设你有一个功能:

void doit(CLASS c);

如果使用实际参数调用它,编译器必须调用复制构造函数,以便不能修改原始参数:

CLASS c1;
doit(c1);

但现在考虑一个不同的例子,假设你像这样调用你的函数:

doit(c1 + c1);

operator+将不得不创建一个临时对象(右值)。 代替在调用doit()之前调用复制构造函数,编译器可以传递由operator+创建的临时文件,并将其传递给doit()


这里是一个例子:

#include <vector>
#include <climits>

class BigCounter {
 public:
   BigCounter &operator =(BigCounter b) {
      swap(b);
      return *this;
   }

   BigCounter next() const;

   void swap(BigCounter &b) {
      vals_.swap(b);
   }

 private:
   typedef ::std::vector<unsigned int> valvec_t;
   valvec_t vals_;
};

BigCounter BigCounter::next() const
{
   BigCounter newcounter(*this);
   unsigned int carry = 1;
   for (valvec_t::iterator i = newcounter.vals_.begin();
        carry > 0 && i != newcounter.vals_.end();
        ++i)
   {
      if (*i <= (UINT_MAX - carry)) {
         *i += carry;
      } else {
         *i += carry;
         carry = 1;
      }
   }
   if (carry > 0) {
      newcounter.vals_.push_back(carry);
   }
   return newcounter;
}

void someFunction()
{
    BigCounter loopcount;
    while (true) {
       loopcount = loopcount.next();
    }
}

somefunctionloopcount = loopcount.next(); 复制精华大大受益。 如果不允许复制elision,则该行将需要3次调用复制构造函数和一个相关联的调用到析构函数。 随着被允许复制省略,它可以降低到1调用拷贝构造函数中,明确一个内部的BigCount::next()其中newcounter声明。

如果operator =已被声明和定义如下:

BigCounter &BigCounter::operator =(const BigCounter &b) {
   BigCounter tmp(b);
   swap(tmp);
   return *this;
}

那么必须有2次复制构造函数的调用,即使是复制删除也是如此。 一个构造newcounter ,另一个构造tmp 。 如果没有复制elision,那么仍然会有3.这就是为什么声明operator =因此它的参数需要调用复制构造时,对赋值运算符使用“复制和交换”惯用法时可以进行优化。 当调用复制构造函数来构造参数时,它的调用可能会被忽略,但如果它被调用来创建局部变量,它可能不会被调用。

链接地址: http://www.djcxy.com/p/12671.html

上一篇: What is copy elision and how does it optimize the copy

下一篇: Copy constructor and = operator overload in C++: is a common function possible?