常量结构的指针成员

Pointer members of const struct

本文关键字:成员 指针 结构 常量      更新时间:2023-10-16

我有一个看起来像这样的类:

class S
{
public:
int* data;
S() : data(new int[10]) {}
};

构造函数分配10 个整数的内存,默认复制构造函数按预期仅复制指针本身而不是内容。

即使有一个S实例具有const修饰符,我也可以修改data指向的数据,因为该数据本身没有const修饰符。我可以通过data私有并且仅允许通过非const方法进行写入访问来避免这种情况,如下所示:

class S
{
private:
int* data;
public:
S() : data(new int[10]) {}
int& operator(size_t i)
{
return data[i];
}
const int& operator(size_t i) const
{
return data[i];
}
};

但是现在我可以使用复制构造函数来规避S实例的const性,如下所示:

void main()
{
const S a; // Allocates memory
S b(a); // Also points to memory allocated for a
b(1) = 3; // Writes to a even though it is not supposed to be mutable
}

解决此问题的优雅方法是什么(可能使用模板)?

  • const S实例指向的数据不应仅使用此实例而可变。
  • 复制
  • 构造函数应仅复制指针,而不应创建数据的深层副本。
  • const SS都应该可以通过复制构造函数创建,给定一个S实例,以便const实例无法修改数据,但非const实例可以。

通过在复制构造函数中提供两个不同的复制构造函数,可以知道正在复制的对象是否const,一个采用const参数,另一个不接受。编译器将选择与传递的参数匹配的版本。在构造函数中设置一个标志,以便在执行非 const 操作时可以引发错误。

避免问题中显示的内存泄漏的最佳方法是使用像std::shared_ptr这样的智能指针,而不是原始指针。不幸的是,shared_ptr适用于单个对象,而不是数组;解决方法是可能的,如此堆栈溢出问题。我现在不会尝试解决这个问题,下面的代码仍然有泄漏。

为了完整,您应该遵循三法则,并提供operator=和析构函数。我把这个留给读者作为练习。

class S
{
private:
int* data;
bool is_const;
public:
S() : data(new int[10]), is_const(false) { data[1] = 42; }
S(const S& other) : data(other.data), is_const(true) {}
S(S& other) : data(other.data), is_const(false) {}
int& operator()(size_t i)
{
if (is_const)
throw std::logic_error("non-const operation attempted");
return data.ptr[i];
}
const int& operator()(size_t i) const
{
return data.ptr[i];
}
};

查看实际操作:http://ideone.com/SFN89M

删除S的复制构造函数(和赋值运算符)。 创建一个新的代理类 (SCopy),其中包含指向S对象的指针(该指针传递给SCopy的构造函数)。 然后,SCopy将实现const int &operator() const而不是非常量版本。

然后,这将允许您在S中实现析构函数,以释放当前泄漏的内存。