移动对象而不使用移动构造函数

时间:2016-12-12 11:35:17

标签: c++ move move-constructor implicit-constructor

还有一次这个问题,但相关的问题没有回答我的问题。

标准非常明确:

  

12.8复制和移动类对象,
  §9
   如果类X的定义没有显式地声明一个移动构造函数,那么当且仅当存在构造函数时,将默认将其声明为默认值    - X没有用户声明的拷贝构造函数,
   - X没有用户声明的复制赋值运算符,
   - X没有用户声明的移动赋值运算符,
   - X没有用户声明的析构函数,以及
   - 移动构造函数不会被隐式定义为已删除   [注意:当未隐式声明或显式提供移动构造函数时,否则将调用移动构造函数的表达式可能会调用复制构造函数。 - 结束说明]

所以,在注意到最后的“Note”之前,我预计这段代码会无法编译(虽然我知道,移动应该回退到复制):

#include <iostream>
using std::cout;
class c
{
public:
    c() { cout << "c::c()\n"; }
    c( std::initializer_list< int > ) { cout << "c::c( std::initializer_list )\n"; };

    c( const c& ) { cout << "c::c( const c& )\n"; }
    c& operator=( const c& ) { cout << "c& c::operator=( const c& )\n"; return *this; }

    ~c() { cout << "c::~c()\n"; }

    void f() {}
};

void f( c&& cr ) { cout << "f()\n"; cr.f(); }

int main()
{
    c x;
    f( std::move( x ) );

    return 0;
}

然后我在最后看到了这个注释,但我仍感到惊讶,上面的代码输出:

  

Ç:: C()
  f()的
  Ç::〜C()

请注意“缺少”c::c( const c& )。然后我添加了

c( c&& ) = delete;
c& operator=( c&& ) = delete;

,结果仍然相同。

我在这里想念什么?

$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609

编译器标志:-s -O0 -march=native -pthread -std=c++11 -Wall -Wextra -DNDEBUG

2 个答案:

答案 0 :(得分:8)

你没有移动任何物体。

std::move实际上非常令人困惑,因为它不会移动任何东西。只有移动构造函数或移动赋值运算符才能移动对象,std::move所做的只是将l值引用(&)转换为r值引用(&&)。

移动构造函数,或者移动赋值运算符可以绑定到r-value-refernce(&&)并窃取对象内容。

答案 1 :(得分:7)

示例中的var casper = require("casper").create(); casper.start(); casper.on('remote.message', function(message) { console.log(message); }); // first evaluate() to create the image casper.thenEvaluate(function() { // create original image to be copied // in the canvas (mandatory to do this first step) var originalImg = document.createElement('img'); originalImg.id = 'myoriginalimg'; originalImg.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AwLDiAQSszC7gAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAACAElEQVRYw+2WMYvbQBBGv5ndFegsdC6cTkWKFIEcpDkCqfLz3aQx5KqQ5lAXHRhHurW12pkUJsThDhLJyAlhXyWJWfHYmdkdIJFIJBKJRCIxJ3T+L8qT591f1yqBElgCqzxfGAOgi7HxfgvszvabqFUBlXNv8rxiXhmTEwHwqk2Mtcid93UI9RladprT26K4tfa1c5W1C2YHAAhAJ1IPQ8X8cRjQtvXFtI5OH7LsJssqYwoiR8QAAAGWRNfM18Ys+h5FMdnMjq2nyrlba2+y7KW1BWDpZxkYwBBZwFoLoBN5cG4XwoQ6M6OiXwDvi+Jdlr1yriQ6OtEJAJjIAhmRAi1RfThM0OJR0UugYq6sLU6cfukgIgCWqCCqrK2Yl5OSyKMyuMrzlTELZvec06mZI1owr4xZ5Xk5924tjMmJ3B8sY8ABOdHxSJtX62KM0+pi9KoBkN9FChAAr9rFOK/WDmi8b2LsRIIqAFV9Gnb8GFQ7kSbGxvvZO3EL1CL1MLSqw3Nmx9dBtVWth6EW2U5K4vh6FFkaUxpzxWwBftKMg2oL3Me46fv142Mtcphb6wBARKy9AjKijIiPx+mPeupVd6r3MX7q+3UIn/f7r5fZrR3g+35vjIooQEQB6FW96jfVB5EvIWz6fh3C5oyr+h8dbP6vMXDuoTmRSCQSiURiPN8BXZXzZJhVHqQAAAAASUVORK5CYII="; document.body.appendChild(originalImg); }) casper.then(function(){ casper.wait(1000); }) // second evaluate() to create the canvas from the image casper.thenEvaluate(function() { // copy the original image in a canvas var imgInInput = document.querySelector('#myoriginalimg'); var imageObj = new Image(); imageObj.src = imgInInput.getAttribute('src'); var canvas = document.createElement('canvas'); canvas.width = 50; canvas.height = 50; var context = canvas.getContext('2d'); context.drawImage( imageObj, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height ); var imageData = context.getImageData(0, 0, 50, 50); var data = imageData.data; // data of the current image var pix = 0; for(var i = 0; i < data.length; i += 4) { pix++; var red = data[i]; var green = data[i+1]; var blue = data[i+2]; var alpha = data[i+3]; data[i+3] = 255; // set transparency to null data[i+1] = 255; // set green at maximum just for the test console.log( pix + "nth pixel" + " red=" + red + " green=" + green + " blue=" + blue + " alpha=" + alpha ); } // overwrite original image context.putImageData(imageData, 0, 0); // Create a <div> to put the canva in var childDiv = document.createElement("div"); childDiv.appendChild(canvas); // Create the parent <div> var parentDiv = document.createElement("div"); parentDiv.setAttribute('id', 'outputimage'); parentDiv.setAttribute('style', 'position: absolute;z-index:9999'); document.body.insertBefore(parentDiv, document.body.firstChild); childDiv.setAttribute('id', 'mydivid'); parentDiv.appendChild(childDiv); }); casper.then(function() { casper.capture("out.png"); casper.echo(casper.getHTML()); }) casper.run(function() { this.exit(); }); 参数是r值参考。这里的参考词很重要。它的行为有点类似于我们从c ++知道的平面旧引用,在c ++ 11在游戏中之前,在一个不调用任何构造函数的术语中......它只是&#34;指向&#34;到你传递的对象......

要调用移动构造函数(或执行其他交换)并使用引用,我们需要进一步转发引用,例如如下:

cr