vendredi 20 avril 2018

Compiler generates default move constructor when it shouldn't

from N3337:

If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

X does not have a user-declared copy constructor, X does not have a user-declared copy assignment operator, X does not have a user-declared move assignment operator, X does not have a user-declared destructor, and the move constructor would not be implicitly defined as deleted.

The first question is: why compiler generates move constructor when it shouldn't (there is user declared destructor and other functions which prevents generation of move constructor). Example program below prints constructorCounter=5 which means that there used move constructor (without move operations value::constructorCounter should be 10)

#include <iostream>
#include <array>

class value {
public:
    value() {
        ++constructorCounter;
    }
  value(const int value)
        : _value(value)
    {
        ++constructorCounter;
  }
    value(const value& other)
        : _value(other._value)
    {
    ++constructorCounter;
  }
  const value& operator=(const value& rhs) {
    _value = rhs._value;
    return _value;
  }
  ~value() { }
static int constructorCounter;
private:
  int _value;
};

int value::constructorCounter = 0;

class array {
public:
//  array() = delete;
//  array(array&&) = delete;
  array(const int size)
    : _size(size), _values(new value[size])
  {
    std::clog << "array(const int size)" << std::endl;
  }
  array(const array& rhs)
        : array(rhs._size)
  {
    std::clog << "array(const array& rhs)" << std::endl;
        for (int i = 0; i < _size; ++i)
            _values[i] = rhs._values[i];
  }
    array& operator=(const array&) {
    std::clog << "array& operator=(const array&)" << std::endl;
  }
  ~array() {
    delete [] _values;
  }
private:
  value* _values;
  int _size;
};

int main(int argc, char *argv[]) {
    array c(array(5));
  std::clog << "constructor counter=" << value::constructorCounter << std::endl;

  return 0;
}

Second related question: why program fail to compile if i disable move constructor array(array&&) = deleted;, why there is no 'fall back' to copy consturctor array(const array&) ?

Aucun commentaire:

Enregistrer un commentaire