Использование конструктора Copy для = перегрузки

У меня есть класс с двумя векторами: int и Str, Теперь я хочу определить конструктор копирования, чтобы порядок элементов был обратным; например если a=(1,Hello),(2,World) и я пишу auto b=a; я получил b=(2,world),(1,hello), Который работает отлично. Проблема, которую я имею, перегружает = оператор, так что конструктор копирования используется. Вот мой класс плюс конструктор копирования:

class grade
{
private:
static int copies;
std::vector<int> i;
std::vector<std::string> s;

public:
grade() {copies++;};
grade (int , std::string );
void printval();
void adder(int , std::string );
int getcount();

grade(grade & obj)
{
std::vector<std::string>::reverse_iterator strIt = obj.s.rbegin();
for (std::vector<int>::reverse_iterator numIt=obj.i.rbegin();
numIt!=obj.i.rend(); ++numIt)
{
this->adder(*numIt, *strIt);
strIt++;
}

}
grade operator =(grade );
};

Когда я перегружаю = оператор конструктор вызывается и проблема в том, что valur не передается в переменную LHS. Вот перегружен =,

grade grade::operator=(grade cpy)
{
grade newer = cpy; //Calls the copy constructor as expected
return cpy;        //No error but blank value is returned to the LHS variable.
}

Моя основная функция:

int main()
{
grade c2(1,"Hello");
grade c1;

c2.adder(4,"World");
c2.printval();
std::cout<<std::endl;
grade c3 = c2;
c3.printval();
std::cout<<std::endl;
c1 = c2;
std::cout<<std::endl;
c1.printval();

return 0;
}

Почему c1 оставить пустым ??

0

Решение

Вы спрашивали: Why does c1 remain blank??

Ответ в том, что оператор присваивания не изменяет сам объект. Вот ваш код:

grade grade::operator=(grade cpy)
{
grade newer=cpy; //Calls the copy constructor as expected
return cpy; //No error but blank value is returned to the LHS variable.
}

Метод возвращается копия входного параметра cpy но не изменяет текущий экземпляр. Когда этот метод выполняется, *this является «переменная LHS», и она не изменяется вообще. В этом методе (перегрузка оператора) вам необходимо изменить переменные-члены текущего экземпляра!

1

Другие решения

Самый простой способ реализовать оператор присваивания — это скопировать и поменять идиому:

grade& operator=( grade other )
{
swap( *this , other );
return *this;
}

Где своп это функция, которая занимает два grades и меняет его значения:

void swap( grade& lhs , grade& rhs )
{
using std::swap;

swap( lhs.first_member  , rhs.first_member  );
swap( lhs.second_member , rhs.second_member );
swap( lhs.third_member  , rhs.third_member  );
...
}

Обратите внимание, что swap() это перегрузка / специализация std::swap(), std::swap() по умолчанию использует оператор назначения для выполнения подкачки, поэтому, если вы используете его, вы ведете к бесконечной рекурсии. Что вам нужно сделать, это написать свою собственную перегрузку подкачки, которая выполняет замену элементов на элементы (как в примере выше).

Обратите внимание, что вы должны использовать неквалифицированную swap() не отключать ADL и позволить компилятору найти кастом swap() перегрузка членов (если они предоставляют) или версия стандартной библиотеки.

3

То, что вы хотите, это идиома копирования и обмена:

#include <algorithm>
grade &grade::operator=( grade cpy ) {
using std::swap;
swap( i, cpy.i );
swap( s, cpy.s );
return *this;
}
1

Измените ваш конструктор копирования и ваш оператор присваивания следующим образом:

grade::grade(const grade& cpy)
{
*this = cpy;
}

grade& grade::operator=(const grade& cpy)
{
if (this == &cpy)
return *this;

std::vector<std::string>::reverse_iterator strIt = cpy.s.rbegin();
for (std::vector<int>::reverse_iterator numIt=cpy.i.rbegin();numIt!=cpy.i.rend();++numIt)
{
this->adder(*numIt, *strIt);
strIt++;
}

return *this;
}

И как общая схема:

object::object(const object& input)
{
*this = input;
}

object& object::operator=(const object& input)
{
if (this == &input)
return *this;

Deallocate();
Allocate(input);
Initialize(input);

return *this;
}
0