我正在追赶现代C ++,练习移动语义。
我做了一个非常简单的测试用例:
我注意到当实例被销毁时,两个析构函数都被称为:
我的代码删除nullptr令我感到不舒服,这是一些问题:
我的测试输出(下面的代码)是:
Test 5
new 0x7512b0
move_new 0x7512b0
delete[] 0x7512b0
delete[] 0
delete [] 0输出是磨碎我齿轮的原因。
主要内容:
#include <iostream>
#include "test5.h"
int main()
{
std::cout << "Test 5" << std::endl;
test5 rule5;
test5 rule5move = std::move(rule5);
// rule5 = std::move(rule5move);
return 0;
}
这是test5.h:
#ifndef TEST5_H
#define TEST5_H
class test5
{
public:
test5(): data(new float[10]){
std::cout << "\tnew " << data << std::endl;
for (int i = 0; i < 10; i++)
data[i] = float(i);
}
~test5(){
std::cout << "\tdelete[] " << data << std::endl;
delete[] data;
}
// copy constructor
test5(const test5& t) : data(new float[10]){
std::cout << "\tcopy " << data << std::endl;
std::copy(t.data, t.data + 10, data);
}
// copy operator
test5& operator=(const test5& t){
std::cout << "\tassign " << data << std::endl;
std::copy(t.data, t.data + 10, data);
return *this;
}
// move constructor
test5(test5&& t): data(new float[10]){
delete[] data;
data = t.data;
std::cout << "\tmove_new " << data << std::endl;
t.data = nullptr;
}
// move operator
test5& operator=(test5&& t){
delete[] data;
data = t.data;
std::cout << "\tmove_assign " << data << std::endl;
t.data = nullptr;
return *this;
}
private:
float* data;
};
#endif // TEST5_H
答案 0 :(得分:2)
那是(删除nullptr)甚至是有效的操作(即是否导致UB;最终会导致我的应用程序崩溃)?
删除nullptr
是禁止操作。是有效的。根据在线CPP reference:
如果expression的计算结果为空指针值,则不会调用析构函数,也不会调用释放函数。
我认为您的move构造函数和move赋值运算符不正确。为什么仍要使用原始指针?
如果您正在赶上现代C ++(如前所述),则应该使用smart pointers。