![](/img/trans.png)
[英]Can Lvalue Reference be bounded to Rvalue Reference? What will happen during the process?
[英]What happen when a lvalue assigned to a rvalue reference? No destruction of the temporary object?
#include <iostream>
using namespace std;
#include <cstring>
class Word{
private:
char* ptr = nullptr;
public:
Word(){
cout << "default constructor" << endl;
}
Word(const char* sentence):ptr{new char [strlen(sentence)+1]}{
strcpy(ptr, sentence);
cout << "conversion constructor: " << ptr << endl;
}
Word(const Word& w):ptr{new char [strlen(w.ptr)+1]}{
strcpy(ptr, w.ptr);
cout << "copy constructor: "<< ptr << endl;
}
~Word(){
cout << "destructor: " << ptr << endl;
}
};
int main(){
Word a ("A stands for apple!");
Word&& b = "B stands for Banana, rvalue ref";
b = a;
}
我的Eclipse結果:
conversion constructor: A stands for apple!
conversion constructor: B stands for Banana, rvalue ref
destructor: A stands for apple!
destructor: A stands for apple!
我的延伸:
conversion constructor: A stands for apple!
conversion constructor: B stands for Banana, rvalue ref
destructor: B stands for Banana, rvalue ref
destructor: A stands for apple!
destructor: A stands for apple!
我對這一步感到困惑。
b = a;
將a分配給b時,可以假設首先銷毀b持有的臨時對象(cstring為“ B代表Banana,rvalue ref”),然后將a的值分配給b。 為什么在Eclipse的結果中,它不執行對臨時對象的銷毀?
您的期望是錯誤的。 破壞不可能超過建築。
將a分配給b時,它可能會假設首先破壞臨時對象
b
號指的是臨時對象。 分配給對象不會導致對象被破壞。
發生的事情是: Word
隱式生成的賦值運算符將分配所有成員。 因此,分配后的前值b.ptr
被泄露,並具有相同的值(指向相同的字符串)作為a.ptr
。
b = a;
正在調用賦值運算符,而不是副本構造函數。 如果明確刪除,則代碼將無法編譯:
// trimmed...
Word(const Word& w):ptr{new char [strlen(w.ptr)+1]}{
strcpy(ptr, w.ptr);
cout << "copy constructor: "<< ptr << endl;
}
Word& operator = (const Word& w) = delete;
編譯行:
$ g++ rvalue-ref.cpp -o rvalue-ref
rvalue-ref.cpp: In function ‘int main()’:
rvalue-ref.cpp:45:9: error: use of deleted function ‘Word& Word::operator=(const Word&)’
b = a;
^
rvalue-ref.cpp:20:15: note: declared here
Word& operator = (const Word& w) = delete;
^~~~~~~~
編譯器將提供一個默認的賦值運算符,因此您問題中的代碼就是利用它。 要查看正在發生的情況,請添加復制分配和移動分配運算符。
Word& operator = (const Word& w) {
auto temp = new char [strlen(w.ptr)+1];
strcpy(temp, w.ptr);
delete [] ptr;
ptr = temp;
cout << "assignment operator: " << ptr << endl;
return *this;
}
Word& operator = (Word&& w) {
std::swap(ptr, w.ptr);
cout << "swap operator: " << ptr << endl;
return *this;
}
有了這些,我得到了預期的輸出:
conversion constructor: A stands for apple!
conversion constructor: B stands for Banana, rvalue ref
assignment operator: A stands for apple!
destructor: A stands for apple!
destructor: A stands for apple!
順便說一句,您正在泄漏內存。 您的析構函數應如下所示:
~Word(){
cout << "destructor: " << ptr << endl;
delete [] ptr;
}
$ valgrind ./rvalue-ref
==10736== Memcheck, a memory error detector
==10736== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10736== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10736== Command: ./rvalue-ref
==10736==
conversion constructor: A stands for apple!
conversion constructor: B stands for Banana, rvalue ref
assignment operator: A stands for apple!
destructor: A stands for apple!
destructor: A stands for apple!
==10736==
==10736== HEAP SUMMARY:
==10736== in use at exit: 0 bytes in 0 blocks
==10736== total heap usage: 5 allocs, 5 frees, 73,800 bytes allocated
==10736==
==10736== All heap blocks were freed -- no leaks are possible
==10736==
==10736== For counts of detected and suppressed errors, rerun with: -v
==10736== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
您還可以使用復制/交換慣用語(如下)實現賦值運算符。 由於臨時原因,這將添加一個額外的構造函數/析構函數輸出,但這是一個好的做法。
Word& operator = (const Word& w) {
Word temp(w);
std::swap(ptr, temp.ptr);
cout << "assignment operator: " << ptr << endl;
return *this;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.