Je suis toujours nouveau en C++, alors portez-moi. J'essayais d'en savoir plus sur le fonctionnement de std :: move et j'ai vu un exemple où ils utilisaient std :: move pour déplacer la chaîne vers une fonction différente, puis montraient en utilisant std :: cout qu'il ne restait aucune chaîne. Je pensais cool, nous allons voir si je peux faire ma propre classe et faire la même chose:Que fait String ce que je ne fais pas? C++ 11
#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;
}
Et voici ma sortie:
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.
Comme vous pouvez le voir, il se bloque lors de son entrée g la deuxième fois, jamais même à l'opérateur < <() fonction. Comment se fait-il que la chaîne std :: string s vide puisse être transmise à g où mon entier vide écrase le programme?
Édition: Correction d'un nouvel int contre une nouvelle erreur int []. Merci à n.m. Votre "entier vide" bloque le programme car il contient un pointeur nul.
Un constructeur de déplacement roulé à la main utilise typiquement 'std :: move' pour déplacer des membres. – Peter
Merci pour l'aide, qui a résolu le problème. Ce qui si je comprends bien était que dans le constructeur de déplacement (et l'opérateur d'affectation) je traitais i.m_i comme lvalue plutôt que comme valeur. Est-ce correct? – davidbear