Как правильно определить операции, что компилятор не уходил в warning?
Подскажите, пожалуйста, как можно поправить такую ошибку(да, на самом деле это варнинг, но все же)? Суть в том , что создал свой класс, для него определил операции, в качестве результат операций возвращаю объект класса, который был создан внутри. Ниже привожу ошибку, оператор присваивания, операции и определение класса, привел реализацию функций, которые могут повлиять на появление данной ошибки. Не совсем понимаю,в чем именно проблема.
Ошибка
functions.cpp: In member function 'IntPlaneSet IntPlaneSet::operator^(const IntPlaneSet&)':
14:06functions.cpp:58:12: error: implicitly-declared 'constexpr IntPlaneSet::IntPlaneSet(const IntPlaneSet&)' is deprecated [-Werror=deprec ated-copy] 58 | return r; | ^ functions.cpp:30:14: note: because 'IntPlaneSet' has user-provided 'IntPlaneSet& IntPlaneSet::operator=(const IntPlaneSet&)' 30 | IntPlaneSet& IntPlaneSet::operator=(const IntPlaneSet& a) | ^~~~~~~~~~~
Оператор присваивания
IntPlaneSet& IntPlaneSet::operator=(const IntPlaneSet& a)
{
SetZero();
CopyOnly(a);
return *this;
}
Операция
IntPlaneSet IntPlaneSet::operator^(const IntPlaneSet& a)
{
IntPlaneSet r = IntPlaneSet(max(this->x1,a.x1),max(this->x2,a.x2),max(this->y1,a.y1),max(this->y2,a.y2));
r.b_s = this->b_s ^ a.b_s;
return r;
}
Так определен класс
#pragma once
#include <cstdio>
#include <cmath>
#include <bitset>
#include <iostream>
#include <cstdlib>
#include <random>
#define x_1 -10
#define y_1 -10
#define x_2 -10
#define y_2 10
#define x_3 10 //допустимые границы, в которых можно задать множество задаются жестко в начале программы
#define y_3 -10
#define x_4 10
#define y_4 10
#define x_size x_3 - x_1 + 1
#define y_size y_2 - y_1 + 1
#define SIZE (x_size)*(y_size)//размер bitset
#define TEST 2 //число массивов в тесте
using namespace std;
class IntPlaneSet
{
int x1,x2,y1,y2;
public:
bitset<SIZE> b_s;
class iterator
{
int cur;
IntPlaneSet* S;
public:
iterator(IntPlaneSet *a= NULL)
{
if (a!=NULL)
{
this->cur = a->FirstNonZero();
this->S = a;
}
else
{
this->cur = -1;
this->S=NULL;
}
}
int operator!=(const iterator &b);
int operator==(const iterator &b);
void operator++();
void operator++(int);
pair<int, int> operator*();
};
IntPlaneSet(int x1=x_1,int x2=x_3,int y1=y_1, int y2=y_2,int rand_key = 0 )
{
this->x1=x1;
this->x2=x2;
this->y1=y1;
this->y2=y2;
this->b_s=( 0 );
if (rand_key == 1)
{
std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> ValsX(x1,x2);
std::uniform_int_distribution<int> ValsY(y1,y2);
for(int i = 0;i<abs(x2-x1)*abs(y2-y1);i++)
{
int x=ValsX(rng);
int y = ValsY(rng);
int index = ((y - y_1)*((x_3 - x_1)+1)) + ((x - x_1));
this->b_s[index]=1;
}
}
}
~IntPlaneSet()
{
this->SetZero();
}
void SetZero()
{
this->b_s = ( 0 );
}
pair<int, int> GetValue(int a);
void AddValue(const int x,const int y);
void DeleteValue(const int x,const int y);
void Print()
{
int index=0;
cout << "Bitset : ( "<< this->b_s << " )\n"<< endl;
for(int i=y_2;i>y_1-1;i--)
{
for (int j=x_1;j<x_3+1;j++)
{
index = ((i - y_1)*((x_3 - x_1)+1)) + ((j - x_1));
cout << this->b_s[index] << " ";
}
printf("\n");
}
}
void Check(const int x,const int y);
int* Borders();
void ChangeBorders(int x1, int x2, int y1, int y2);
void ChangeBorders(int* a);
int** MinMax();
IntPlaneSet operator&(const IntPlaneSet& a);
IntPlaneSet operator|(const IntPlaneSet& a);
IntPlaneSet operator^(const IntPlaneSet& a);
IntPlaneSet operator~();
void CopyOnly(const IntPlaneSet& a);
IntPlaneSet& operator=(const IntPlaneSet& a);
int FirstNonZero();
int NextNonZero(int a);
iterator begin()
{
return iterator(this);
}
iterator end()
{
return iterator(NULL);
}
};
Ответы (2 шт):
IntPlaneSet r = IntPlaneSet(max(this->x1,a.x1),max(this->x2,a.x2),max(this->y1,a.y1),max(this->y2,a.y2));
IntPlaneSet r(max(this->x1,a.x1),max(this->x2,a.x2),max(this->y1,a.y1),max(this->y2,a.y2));
Вы написали для своего класса деструктор и копирующий оператор присваивания, но не написали копирующий конструктор, и перемещающие конструктор и оператор присваивания.
Поэтому... (см. ряды "destructor" и "copy assignment")

(за таблицу спасибо Говарду Хиннанту)
Поэтому компилятор не стал генерировать перемещающие операции (5,6 колонки).
Но копирующий конструктор сгенерировал (3 колонка), хотя это поведение считается устаревшим (deprecated), начиная с C++11.
А вы где-то использовали этот копирующий конструктор, поэтому компилятор вас и предупреждает, что надеяться на его наличие не стоит.
Решение - убрать самодельный деструктор и копирующее присваивание. Все равно они ничего полезного не делают.
Если бы в них было что-то полезное, то есть другой вариант: явно попросить компилятор сгенерировать недостающие операции
IntPlaneSet(const IntPlaneSet &) = default;
IntPlaneSet(IntPlaneSet &&) = default;
// IntPlaneSet &operator=(const IntPlaneSet &) = default;
IntPlaneSet &operator=(IntPlaneSet &&) = default;
// ~IntPlaneSet() = default;
Советую почитать про правило трех/пяти/нуля.
Народная мудрость гласит, что у класса должны быть, на выбор:
- Деструктор и копирующие операции (всего 3)
- Деструктор и копирующие и перемещающие операции (всего 5)
- Ничего из пяти - самый распространенный вариант (0)
А если комбинация какая-то другая, то это почти всегда ошибка, как в вашем случае.