[英]Will c++ range-based for loop call the destructor of iterator?
在嘗試實現雙指針的迭代器時,我發現了一些有趣的東西:
class A
我有一個名為A
的 class ,它將為整數序列( _ori_aa
)分配一些 memory 。
class A {
public:
// constructor and destructor
// ...
Iter<int> aa() const {
Iter<int> _iter;
_iter.set(_aa, _len);
return _iter;
}
private:
const int _len;
int * _ori_aa; // sequence of numbers: {0, 1, 2, 3}
int ** _aa; // pointers to _ori_aa: {_ori_aa, _ori_aa+1, ...}
};
struct Iter
還有一個名為Iter
的結構,它可以幫助我在A
object 中迭代雙指針_aa
。
為了觀察,我在構造函數和析構函數中打印了自身( this
)的 memory 地址。
function meow()
也打印 memory 地址,但它用於手動調用。
template <typename T>
struct Iter {
Iter() { cout << '+' << this << endl; }
~Iter() { cout << '-' << this << endl; }
// ...
void meow() {
cout << '?' << this << endl;
}
// ...
};
main()
在主function中,
A
的 object ,然后調用aa()
,這將生成一個Iter
object並按值返回。Iter
的 object 並手動調用meow()
以查看其地址。int main() {
A a;
Iter<int> aa = a.aa(); // copy by value
aa.meow();
for(const int & n : aa) {
cout << n << endl;
}
cout << "-------" << endl;
}
這是程序的output:
+0x7ffee567a9b0
?0x7ffee567a9b0
0
1
2
3
-0x7ffee567a988
-------
-0x7ffee567a9b0
我的問題是:
aa()
中創建_iter
時會打印第一個地址,但是什么時候調用析構函數? 我認為_iter
將在aa()
返回后被銷毀,而它似乎沒有這樣做。aa
( main()
中的局部變量)被破壞時會打印最后一個地址。 既然和_iter
的地址一樣,那是不是意味着 _iter 的_iter
已經被釋放了呢? 那么為什么沒有調用析構函數呢?-std=c++17
以下是完整的代碼,
#include <iostream>
using namespace std;
template <typename T>
struct Iter {
Iter() { cout << '+' << this << endl; }
~Iter() { cout << '-' << this << endl; }
T ** pp {nullptr};
int len {0};
int it {0};
void meow() {
cout << '?' << this << endl;
}
void set(T ** pi, int l) {
pp = pi;
len = l;
}
Iter & begin() {
it = 0;
return *this;
}
int end() const {
return len;
}
T & operator*() {
return *pp[it];
}
bool operator!=(int rhs) {
return this->it < rhs;
}
Iter & operator++() {
++it;
return *this;
}
};
class A {
public:
A() : _len(4) {
_ori_aa = new int [_len];
_aa = new int * [_len];
for(int i = 0; i < _len; i++) {
_ori_aa[i] = i;
_aa[i] = _ori_aa + i;
}
}
~A() {
delete [] _aa;
delete [] _ori_aa;
}
Iter<int> aa() const {
Iter<int> _iter;
_iter.set(_aa, _len);
return _iter;
}
private:
const int _len;
int * _ori_aa;
int ** _aa;
};
int main() {
A a;
Iter<int> aa = a.aa(); // copy by value
aa.meow();
for(const int & n : aa) {
cout << n << endl;
}
cout << "-------" << endl;
}
感謝您的閱讀!
基於范圍的 for 語句:
for (const int & n : aa) {
cout << n << endl;
}
只是以下的語法糖(參見cppref ):
{
auto&& __range = aa;
auto __begin = __range.begin();
auto __end = __range.end();
for (; __begin != __end; ++__begin) {
const int & n = *__begin;
cout << n << endl;
}
}
這應該可以幫助您了解其他Iter
的構建位置和銷毀位置。
請注意,該程序中恰好構造了兩個Iter
對象:一個名為aa
,另一個在脫糖 for 語句中名為__begin
。 aa()
中名為_iter
的那個是在aa
中構建的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.