在分配对象时保留constness

时间:2014-01-06 21:52:21

标签: c++

分配时是否可以保留对象的常量?考虑一个持有动态内存指针的类,在分配时需要软拷贝。 (有一些更复杂的逻辑,包括引用计数,但它与问题无关)。

class Vec {
private:
    int *data_; // dynamic array
public:
    int * Data() { return data_;} // access for modification
    const int * Data() const { return data_;} // read only access
    Vec subVec(int pos) { // create writable submat
        Vec ret; 
        ret.data_ = &data_[pos];
        return ret;
    }
    const Vec subVec(int pos) const { // create read only submat
        Vec ret; 
        ret.data_ = &data_[pos];
        return ret;
    }
};
void processVec(const Vec & src) {
    src.Data()[0] = 1; // not allowed, since src const
    Vec subVec = src.subVec(2); // call const version of subVec and create
                                // a soft copy - wrapper for a part of array.
                                // Assignment creates a copy, which removes constness
    subVec.Data()[0] = 1; // allowed! Since subVec is a copy, but modifies 
                          // identical dynamic memory from the wrapped src!
}

我希望subVec.Data()[0] = 1;失败,因为它应该保持const。

3 个答案:

答案 0 :(得分:2)

您的问题是,您正在定义一个指向某个对象的智能指针,但是您将智能指针的常量(类似于Foo* const bar;)与对象的常量(类似于const Foo* bar;)混淆)。你需要的是将指针的常量与对象的常量分开。

通过使用两个智能指针类而不是一个智能指针类,可以相对容易地实现:基类,实现const对象的智能指针,以及实现非智能指针的派生类const对象。

有了这个,你总是可以降级你的智能指针到“const”基类,make copy free“const”副本等等。你甚至可以在派生的非“const”智能指针类中添加一个构造函数。采用“const”基类的智能指针来制作数据的深层副本。

答案 1 :(得分:1)

在使用const或非const对象时,我会通过创建不同的返回类型来模仿iteratorconst_iterator习语。这里有一个示例,它实现了对subVec的const调用的不同类型:

class Vec {
 // ...
public:
 // ...

    const int * Data() const { return data_;} // read only access
    Vec subVec(int pos) { // create writable submat
        Vec ret; 
        ret.data_ = &data_[pos];
        return ret;
    }

    class SubVec
    {
    private:
        const int* data_;
    public:
        SubVec(const int* data) : data_(data) {}
        const int * Data() const { return data_;} // read only access
    };

    const SubVec subVec(int pos) const { // create read only submat
        SubVec ret(&data_[pos]);        
        return ret;
    }    
};

这将生成the error you want in the const casewill compile in the non const case。使用auto可以为代码用户编写更简单的代码。

答案 2 :(得分:0)

IIUC,const或非const的元素在运行时分配,因此类型系统(它是静态的)无法帮助你。您需要为每个元素存储一些布尔标志,并对赋值执行运行时检查以查看是否允许。