从const指针

时间:2016-02-10 23:03:39

标签: c++ pointers const

是否有可能强制编译器在我的类中传播const-qualifier,以便为构造函数提供const指针?请考虑以下代码:

struct T
{
    T(int * a, int * b): 
        a(a), b(b) {}

    int * a;
    int * b;
};

int a = 1, b = 2;
const int * aRef = &a;
const int * bRef = &b;
const T obj(aRef, bRef); // error

显然不允许这样做,因为构造函数接受int *,而不是const int *。有没有办法达到相同的效果,如果无意修改类a的{​​{1}}对象中bconst的数据? / p>

编辑这是一个稍微复杂的例子,更接近实际问题。想象一下,我按顺序传递了许多T的大数组(比如连续1000个整数),我想评估int[]中位置的最大元素运行(即运行最大值)也是1000-int vector)。当我将k传递给传入数组的开头时,我设计了一个struct

const int *

struct ArrayWithMax { public: ArrayWithMax(int * array) : array(array) {} void Max(const ArrayWithMax& rhs); private: int * array; } 显然会循环遍历两个数组,并将最大值(ArrayWithMax::Max)分配给对象max(this->array[k], rhs.array[k]。为简洁起见,我将跳过代码。

现在,我将存储结果的变量必须是非常量的(因为max-array的元素将会改变)。但是,我收到的更新是array。对我来说最简单的方法是从const int *初始化const ArrayWithMax,这正是问题试图实现的目标。

3 个答案:

答案 0 :(得分:3)

看起来你想要的是:

const T obj(aRef, bRef);

导致一个对象无法修改指针所指向的整数。这意味着让成员指针为int const* constint const*

现实是const只是传播给成员,使它们都成为int* const,这只是意味着一旦指针被设置,它们就无法改变。

您可以通过以下方式实现您的目标:

template<typename Type>
struct T {
    T(Type* a, Type* b): 
        a(a), b(b) {}

    Type* a;
    Type* b;
};

然后:

int a = 1, b = 2;
int const* aRef = &a;
int const* bRef = &b;
T<int const> obj(aRef, bRef);

Live demo

如果您还希望指针本身为const,则可以使用:

T<int const> const obj(aRef, bRef);

答案 1 :(得分:1)

我想我明白了。您希望先使用自己的可写存储ArrayWithMax拨打int*,然后再使用收到的非可变存储int const *来调用它。然后,您将这些不可变的ArrayWithMax传递给您的可变ArrayWithMax::Max()以评估您的最大运行时间。假设这是你想要的,我有点同意vlad_tepesch,因为设计可能需要一些工作。也就是说,我会用这样的模板来做:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <iterator>

using namespace std;

const size_t ARRAY_SIZE = 2;   // hardcoded for now; it could be 1000

template <typename T>
class ArrayWithMax
{
public:
    ArrayWithMax(T array) : array_(array){}

    // Max will accept any class, as long as it provides U::begin() const
    // Max will not be generated when type T is const.
    template <typename U>
    void Max(const U& rhs)
    {
        transform(begin(), end(), rhs.begin(), begin(),
            [] (auto a, auto b) { return max(a, b); } );
    }

    T begin() { return array_; }
    T end() { return array_+size(); }

    T begin() const { return array_; }
    T end() const { return array_+size(); }
    size_t size() const { return ARRAY_SIZE; }

private:
    T array_;
};

int main()
{
    // some data to test with
    int someArray[ARRAY_SIZE];
    someArray[0] = 1;
    someArray[1] = 2;
    int const * received = someArray;

    int someArray2[ARRAY_SIZE];
    someArray2[0] = 0;
    someArray2[1] = 8;
    int const * received2 = someArray2;

    // to store max
    int myStorage[ARRAY_SIZE];
    memset(myStorage, 0, sizeof(myStorage));

    int* aWithMax = myStorage;

    // first mutable ArrayWithMax with myStorage
    ArrayWithMax<int*> a(aWithMax);

    copy(a.begin(), a.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    // other ArrayWithMax with const int*
    ArrayWithMax<const int*> receivedArray(received);
    a.Max(receivedArray);

    copy(a.begin(), a.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    // and another
    ArrayWithMax<const int*> receivedArray2(received2);
    a.Max(receivedArray2);

    copy(a.begin(), a.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
}

该程序编译如下,它产生以下输出:

Luiss-Air:const luis$ g++-5.3.0 -std=c++14 ArrayWithMax.C 
Luiss-Air:const luis$ a.out
0 0 
1 2 
1 8 
Luiss-Air:const luis$

如果ArrayWithMax仅计算运行最大值,请考虑使用std :: transform:

    // this does what you want to do with your class
    transform(aWithMax, aWithMax+ARRAY_SIZE, received, aWithMax,
        [] (auto a, auto b) { return max(a, b); });

答案 2 :(得分:0)

您可以使用继承,如下所示:

struct CT
{
    CT(int const * a, int const * b) :
        a(a), b(b) {}

    int const * ca;
    int const * cb;
};

struct T : CT
{
    T(int * a, int * b) :
        CT(a, b) {}

    int * a() const { return const_cast<int *>(ca); }
    int * b() const { return const_cast<int *>(cb); }    
};

或者,您可以制作CTT个不相关的类型,并提供从TCT的隐式转换。

我真的不希望通过const TT进行此操作。这是非直观的。此外,您还必须禁用默认的copy-ctor。否则,总是可以从const-ref创建非const副本,然后使用该非const副本来修改*a*b