保证const指针的成员变量的const性

Ensuring constness of member variable of const pointer

本文关键字:const 变量 成员 保证 指针      更新时间:2023-10-16

为什么这段代码编译得很顺利?

class myvector
{
public:
    myvector()
    {
        begin = new double[10];
        end = begin+10;
    }
    ~myvector()
    {
        delete[] begin;
    }
    double *begin;
    double *end;
};
class VectorWorker
{
public:
    VectorWorker(){}
    void doWork(const myvector *v)
    {
        for (int i=0;i<10;i++)
            v->begin[i] = i; // I don't want this to compile! I'd prefer compiler says me I can't modify v->begin
    }
    void doWork2(const myvector *const v) const
    {
        for (int i=0;i<10;i++)
            v->begin[i] = i; // I don't want this to compile!  I'd prefer compiler says me I can't modify v->begin
    }
    void doWork3(const myvector &v)
    {
        for (int i=0;i<10;i++)
            v.begin[i] = i; // I don't want this to compile!  I'd prefer compiler says me I can't modify v->begin
    }
};
int main(int, char*[])
{
    myvector x;
    VectorWorker work;
    work.doWork(&x);
    work.doWork2(&x);
    work.doWork3(x);
    return 0;
}

我希望通过const myvector *vVectorWorker::doWork方法,应该确保我在myvector中的变量是完整的,但实际上它们被修改了。如何确保doWork方法允许进行只读操作?

实际上我不能修改double *begindouble *end变量为const double *,因为它们来自第三方库。但是,我如何确保它们在通过它们所属的类的实例传递时保持完整,即使通过const pointer ?

代码可在coliru: http://coliru.stacked-crooked.com/a/bb43fbebebdb5872

使用accessors:

class myvector
{
public:
    //previous code
    const double* get_begin() const { return begin; }
    const double* get_end() const { return end; }
    double* get_begin() { return begin; }
    double* get_end() { return begin; }
private:
    double *begin;
    double *end;
};

所以不能使用double ptr。如果你真的想让它"正常工作",你可以创建一个自定义的DoublePtr类型:

class DoublePtr
{
public:
    DoublePtr() { _ptr = 0; }
    DoublePtr(double* ptr) { _ptr = ptr; }
    //index operators provide lookups
    double& operator[](int pos) {
        return _ptr[pos];
    }
    const double& operator[](int pos) const {
        return _ptr[pos];
    }
    //casts for backward compatibility
    operator double*() {
        return _ptr;
    }
    operator const double*() const {
        return _ptr;
    }
private:
    double* _ptr;
};
class myvector
{
public:
    myvector()
    {
        buffer = new double[10];
        begin = DoublePtr(buffer);
        end = DoublePtr(buffer+10);
    }
    ~myvector()
    {
        delete[] begin;
    }
    DoublePtr begin;
    DoublePtr end;
private:
    double* buffer;
};

那么VectorWorker代码根本不需要修改。

说了这么多,如果你可以使用它们,访问器似乎是一个更好的方法。

const不可传递;虽然指针本身是const类型(不能设置'begin'),但它指向的值不是const类型。

所以如果不修改myvector(你说这不是一个选项),或者只通过一个只提供const访问的包装器来访问它,你就无法获得这种行为。

这不是一个理想的解决方案-最好是修复myvector可憎(这是从哪个库来的?)。

class myvectorconst
{
private:
    myvector* vec_;
public:
    myvectorconst(myvector* vec) : vec_(vec) {}
    double const* begin() const { return vec_->begin; }
};
class VectorWorker
{
public:
    VectorWorker(){}
    void doWork(const myvectorconst& v)
    {
        for (int i=0;i<10;i++)
            v->begin()[i] = i; // Won't compile.
    }
// ...
};