gpt4 book ai didi

c++ - 为什么析构函数构造的两个对象被调用三次

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:07:26 25 4
gpt4 key购买 nike

这是我对一些 C++11 学习示例的实现。我让所有构造函数和析构函数打印到控制台。但令人惊讶的是,我的构造函数被调用了两次,而析构函数被调用了三次。

似乎出乎意料的是在 0x7fff5fbff6d0。这个对象是什么时候创建的?但为什么没有关联的构造函数调用?

为什么会这样?

template<typename T>
class ArrayWrapper{
public:
ArrayWrapper():data_(nullptr), size_(0){
cout << "Default ctor called "<< this <<endl;
}

ArrayWrapper(size_t n, const T& val) : data_(new T[n]), size_(n){
cout << "ctor_n_val called "<< this << endl;
for_each(data_, data_+size_, [&](T& elem){ elem=val; });
}

ArrayWrapper(const ArrayWrapper& other): data_(new T[other.size_]), size_(other.size_)
{
cout << "copy ctor called "<< this <<endl;
copy(other.data_, other.data_+other.size_, data_);
}

ArrayWrapper(ArrayWrapper&& other): data_(other.data_), size_(other.size_)
{
cout << "move ctor called"<<endl;
other.data_ = nullptr;
other.size_ = 0;
}

ArrayWrapper<T>& operator=(const ArrayWrapper& other){
cout << "copy assignment called" <<endl;
if(this != &other){
delete data_;
data_ = new T[other.size_];
copy(other.begin(), other.end(), begin());
size_ = other.size_;
}
return *this;
}

ArrayWrapper<T> operator=(ArrayWrapper&& other){
cout << "move assignment called " <<this << " <- " <<&other <<endl;
swap(size_, other.size_);
swap(data_, other.data_);
}

~ArrayWrapper(){
cout <<"Destroying " << this << " Size " << size_ <<endl;
}
typedef T* iterator;
typedef const T* const_iterator;

T* begin() {
return data_;
}

T* end(){
return data_ + size_;
}

const T* begin() const {
return data_;
}

const T* end() const {
return data_ + size_;
}

const T* cbegin() const {
return data_;
}

const T* cend() const {
return data_ + size_;
}

size_t size(){
return size_;
}
public:
T* data_;
size_t size_;
};

template<typename T>
ArrayWrapper<T> make_array(size_t n, const T& val){
cout <<"Factory method called"<<endl;
return ArrayWrapper<T>(n, val);
}

template<typename T>
std::ostream& operator<<(std::ostream& os, const ArrayWrapper<T>& arr){
for(const T& elem: arr){ os << elem << ", ";}
return os;
}

int main(){
size_t n = 10;
ArrayWrapper<int> a4(n, 1);
a4 = make_array(n, 4); // move assignment:
cout << "A4: " << a4 << endl;
}

输出:

$ g++-mp-4.8 -std=c++11 move.cpp 

$ ./a.out

ctor_n_val called 0x7fff5fbff6b0

Factory method called

ctor_n_val called 0x7fff5fbff6e0

move assignment called 0x7fff5fbff6b0 <- 0x7fff5fbff6e0

Destroying 0x7fff5fbff6d0 Size 0

Destroying 0x7fff5fbff6e0 Size 10

A4: 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,

Destroying 0x7fff5fbff6b0 Size 10

最佳答案

你的 move 赋值运算符应该返回一个引用:

ArrayWrapper<T>& operator=(ArrayWrapper&& other)
// ^

因为你让它按值返回,但没有 return 语句,你调用了未定义的行为。您应该像复制赋值运算符一样实现它,当然除了 move 资源而不是复制它们:

ArrayWrapper<T>& operator=(ArrayWrapper&& other){
if(this != &other){
delete[] data_;
size_ = other.size_;
data_ = other.data_;
other.size_ = 0;
other.data_ = nullptr;
}
return *this;
}

另外,请注意使用 delete[] 删除动态分配的数组。

关于c++ - 为什么析构函数构造的两个对象被调用三次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16205723/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com