我正在尝试试验5/3/0的规则。编译程序时,我收到警告C26401
,说我必须删除自己不拥有的指针,并且不要在析构函数的行delete[] pChar_;
中删除它。
我同意,在调用move ctor
时,在调用源对象时应用std::swap
时,我特别会在此发布问题。
那么我该如何解决这个问题?
编辑 :如评论中所建议,我可以使用std :: string(好),但我想知道如何在不修改类型的情况下解决此问题让我们说学习:)
using namespace std;
struct A
{
A();
A(int Int, const char* pChar);
A(const A& rhs);
A& operator=(A rhs);
A(A&& rhs);
~A();
void swap(A& rhs);
int Int_ = 0;
char *pChar_ = nullptr;
};
A::~A()
{
std::cout << "----DTOR----" << std::endl;
if (pChar_ != nullptr)
{
delete[] pChar_;
pChar_ = nullptr;
}
}
A::A(int Int, const char* pChar) :
Int_(Int), pChar_(new char[strlen(pChar) + 1])
{
strncpy_s(pChar_, strlen(pChar) + 1, pChar, _TRUNCATE);
}
A::A(const A& rhs) : A(rhs.Int_, rhs.pChar_) {}
A& A::operator=(A rhs)
{
swap(rhs);
return *this;
}
A::A(A&& rhs)
{
swap(rhs);
}
void A::swap(A& rhs)
{
std::swap(this->Int_, rhs.Int_);
std::swap(this->pChar_, rhs.pChar_);
}
int main()
{
A v1{ 1, "Hello" };
{
A v3{ std::move(v1) };
}
}
答案 0 :(得分:1)
我没有可方便地重现您的警告的VS副本,但在我看来,警告来自CPP Code Guidelines,特别是I.11: Never transfer ownership by a raw pointer (T*) or reference (T&):
执法
- (简单)警告删除不是
owner<T>
的原始指针。建议使用标准库资源句柄或使用owner<T>
。
因此解决方案是使用gsl::owner<char *> pChar_ = nullptr;
。请注意,gsl::owner
仅仅是为了帮助代码读者(人类或工具)提供注释,并且不会神奇地使您的代码安全。
据我所见,您的代码看起来还可以。
我遇到的一个问题是ctor:
A(int Int, const char* pChar) :
Int_(Int), pChar_(new char[strlen(pChar) + 1])
{
strncpy_s(pChar_, strlen(pChar) + 1, pChar, _TRUNCATE);
}
这是伪装成安全代码的不安全代码。 strncpy_s
带给您安全感。但是实际上,它绝对不会在代码中执行任何操作(出于安全考虑)。因为如果pChar
出现问题(例如,它不指向以null结尾的字符串),那么strlen
将首先失败。因此,要么说出每个std函数所说的话:pChar
应该是指向以空值结尾的字符串的有效指针,否则应计为UB,或者保护在strlen
处。一旦警惕了,strcpy
就足够了。
您也不必检查Int
是否等于strlen
。他们应该是。