Что делает String, чего я не делаю? C++11
Я все еще новичок в C++, так что терпите меня.
Я пытался узнать больше о том, как работает std:: move, и я увидел пример, в котором они использовали std:: move для перемещения строки в другую функцию, а затем показали с помощью std:: cout, что строки не осталось. Я подумал круто, давайте посмотрим, смогу ли я сделать свой собственный класс и сделать то же самое:
#include <iostream>
#include <string>
class integer
{
private:
int *m_i;
public:
integer(int i=0) : m_i(new int{i})
{
std::cout << "Calling Constructor\n";
}
~integer()
{
if(m_i != nullptr) {
std::cout << "Deleting integer\n";
delete m_i;
m_i = nullptr;
}
}
integer(integer&& i) : m_i(nullptr) // move constructor
{
std::cout << "Move Constructor\n";
m_i = i.m_i;
i.m_i = nullptr;
}
integer(const integer& i) : m_i(new int) { // copy constructor
std::cout << "Copy Constructor\n";
*m_i = *(i.m_i);
}
//*
integer& operator=(integer&& i) { // move assignment
std::cout << "Move Assignment\n";
if(&i != this) {
delete m_i;
m_i = i.m_i;
i.m_i = nullptr;
}
return *this;
}
integer& operator=(const integer &i) { // copy assignment
std::cout << "Copy Assignment\n";
if(&i != this) {
m_i = new int;
*m_i = *(i.m_i);
}
return *this;
}
int& operator*() const { return *m_i; }
int* operator->() const { return m_i; }
bool empty() const noexcept {
if(m_i == nullptr) return true;
return false;
}
friend std::ostream& operator<<(std::ostream &out, const integer i) {
if(i.empty()) {
std::cout << "During overload, i is empty\n";
return out;
}
out << *(i.m_i);
return out;
}
};
void g(integer i) { std::cout << "G-wiz - "; std::cout << "The g value is " << i << '\n'; }
void g(std::string s) { std::cout << "The g value is " << s << '\n'; }
int main()
{
std::string s("Hello");
std::cout << "Now for string\n";
g(std::move(s));
if(s.empty()) std::cout << "s is empty\n";
g(s);
std::cout << "\nNow for integer\n";
integer i = 77;
if(!i.empty()) std::cout << "i is " << i << '\n';
else std::cout << "i is empty\n";
g(i);
std::cout << "Move it\n";
g(std::move(i)); // rvalue ref called
if(!i.empty()) std::cout << "i is " << i << '\n';
else std::cout << "i is empty\n";
g(i);
return 0;
}
И это мой вывод:
Now for string
The g value is Hello
s is empty
The g value is
Now for integer
Calling Constructor
Copy Constructor
i is 77
Deleting integer
Copy Constructor
G-wiz - Copy Constructor
The g value is 77
Deleting integer
Deleting integer
Move it
Move Constructor
G-wiz - Copy Constructor
The g value is 77
Deleting integer
Deleting integer
i is empty
Copy Constructor
Process returned 255 (0xFF) execution time : 7.633 s
Press any key to continue.
Как видите, происходит сбой при повторном входе в g, даже не доходя до функции operator<< (). Как получается, что пустая строка std:: string s может быть передана в g, где мое пустое целое число i вылетает из программы?
Редактировать: Исправлена ошибка нового int против нового int[]. Спасибо нм
1 ответ
Ваше "пустое целое число" приводит к сбою программы, поскольку оно содержит нулевой указатель. Вы пытаетесь разыменовать его, когда используете его в правой части задания.
Пустая строка - это обычная используемая строка. Там нет никаких непроверенных разыменования нулевого указателя в std::string
код.
Вы должны убедиться, что пустое состояние вашего объекта пригодно для использования. Начните с определения конструктора по умолчанию. Имеет ли это смысл для вашего класса? Если нет, то переместить семантику, вероятно, тоже нет. Если да, объект move-from в конструкторе перемещения, вероятно, должен оказаться в том же состоянии, что и объект, созданный по умолчанию. Назначение перемещения может действовать как операция подкачки, поэтому правая сторона может оказаться либо пустой, либо нет.
Если вы не хотите определять пригодное для использования пустое состояние для своего класса и по-прежнему хотите семантику перемещения, вы просто не сможете использовать объект после его перемещения из. Вам все еще нужно убедиться, что пустой объект разрушаем.