为什么析构函数构造的两个对象被调用三次
Why two object constructed by destructors are called for three times
下面是我实现的一些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
语句,你调用未定义的行为。您应该像复制赋值操作符一样实现它,当然,除了移动资源而不是复制它们:
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[]
来删除动态分配的数组。
相关文章:
- 对RValue对象调用的LValue ref限定成员函数
- 检查哪个对象调用了另一个对象的对象方法
- 在 C++ 的 Switch Case 中创建对象后对对象调用方法
- 从 Base 引用对象调用派生类的成员
- 为什么为未删除的对象调用析构函数?
- Qt c++不会为所有对象调用move_slot.为什么?
- 使用在堆栈上创建的对象调用虚拟函数
- 使用基类对象调用Dervied Class函数
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 从类中的对象调用类中的函数的最佳方法
- 派生对象调用的 Base 方法的模板推导
- 如何使用单个对象调用具有相同名称的两个类函数
- 是否可以从另一个类对象调用一个类函数而不继承第一个类
- 如果类没有任何成员变量,则通过临时对象调用类的成员函数的开销是多少?
- 如何对动态数组中的某些对象调用析构函数
- 如何从列表中存储的对象调用成员函数
- 从线程内的对象调用静态方法
- 从成员对象调用方法
- 当包含它的对象调用其析构函数时,unique_ptr是否未分配
- 从对象调用成员对象,错误:引用非常量值的初始值必须是左值