C / C ++:Const Struct中的指针

时间:2022-08-09 21:41:07

How do I force const-ness of the memory pointed to by obj->val1 in the function fn?

如何在函数fn中强制obj-> val1指向的内存的常量?

#include <iostream>

struct foo {
    int* val1;
    int* val2;
    int* val3;
};

void fn( const foo* obj )
{
    // I don't want to be able to change the integer that val1 points to
    //obj->val1 = new int[20]; // I can't change the pointer,
    *(obj->val1) = 20; // But I can change the memory it points to...
}

int main(int argc, char* argv[])
{
    // I need to be able to set foo and pass its value in as const into a function
    foo stoben;
    stoben.val1 = new int;
    *(stoben.val1) = 0;
    std::cout << *(stoben.val1) << std::endl; // Output is "0"
    fn( &stoben );
    std::cout << *(stoben.val1) << std::endl; // Output is "20"
    delete stoben.val1;
    return 0;
}

The code here is pretty self explanitory. I need to be able to make a non-const object and fill it with data, but then pass it to a function where this data cannot be modified. How can I go about this?

这里的代码非常自我解释。我需要能够创建一个非const对象并用数据填充它,然后将其传递给无法修改此数据的函数。我怎么能这样做?

I know I can just pass in a const int pointer, but theoretically, this class contains several other pointers which I will need in "fn" as well.

我知道我可以传入一个const int指针,但理论上,这个类包含了其他几个指针,我也需要它们在“fn”中。

Thanks,

Griff

3 个解决方案

#1


6  

Since you tagged as C++, you could make the member private and make an accessor that returns a const int *. You could originally set the member via your constructor or a friend function.

由于您标记为C ++,因此您可以将该成员设为私有,并创建一个返回const int *的访问器。您最初可以通过构造函数或朋友函数设置成员。

#2


4  

I'm not a C++ person, but in C, I'd handle this through two different struct declarations, one public, one private:

我不是C ++人员,但在C中,我会通过两个不同的结构声明来处理这个问题,一个是公共的,一个是私有的:

#include <stdio.h>
#include <stdlib.h>

struct private_foo {
    int* val1;
    int* val2;
    int* val3;
};

struct public_foo {
    int const * const val1;
    int const * const val2;
    int const * const val3;
};


void fn( struct public_foo * obj )
{
    int local;
    *(obj->val1) = 20; // compile error
    obj->val1 = &local; // compile error
}

int main(int argc, char* argv[])
{
    // I need to be able to set foo and pass its value in as const into a function
    struct private_foo stoben;
    stoben.val1 = malloc(sizeof(int));
    if (!stoben.val1) { return -1; }
    *(stoben.val1) = 0;
    printf("%d", *(stoben.val1) );
    fn( (struct public_foo *) &stoben );
    printf("%d", *(stoben.val1) );
    free(stoben.val1);
    return 0;
}

When I try to compile the above w/ GCC, I get the following compiler errors, since I'm trying to modify read-only memory:

当我尝试编译上面的w / GCC时,我得到以下编译器错误,因为我正在尝试修改只读内存:

temp.c: In function ‘fn’:
temp.c:20: error: assignment of read-only location
temp.c:21: error: assignment of read-only member ‘val1’

#3


2  

You really can't. A const foo specifies that the members inside are const, that is, they are constant pointers to integers, not pointers to constant integers.

你真的不能。 const foo指定里面的成员是const,也就是说,它们是整数的常量指针,而不是指向常量整数的指针。

The proper solution to this would be via encapsulation, hiding these members and providing a public interface. A practical solution, should you be forbidden to modify the struct foo, would be through private inheritance:

对此的正确解决方案是通过封装,隐藏这些成员并提供公共接口。一个实用的解决方案,如果你被禁止修改struct foo,将通过私有继承:

struct foo {
    int* val1;
    int* val2;
    int* val3;
};

struct constFoo : private foo {
public:
   const int* getVal1() { return val1; }
   const int* getVal2() { return val2; }
   const int* getVal3() { return val3; }
};

Of course, you would need to create the appropriate constructors, etc., so that the original foo can be set up.

当然,您需要创建适当的构造函数等,以便可以设置原始foo。

#1


6  

Since you tagged as C++, you could make the member private and make an accessor that returns a const int *. You could originally set the member via your constructor or a friend function.

由于您标记为C ++,因此您可以将该成员设为私有,并创建一个返回const int *的访问器。您最初可以通过构造函数或朋友函数设置成员。

#2


4  

I'm not a C++ person, but in C, I'd handle this through two different struct declarations, one public, one private:

我不是C ++人员,但在C中,我会通过两个不同的结构声明来处理这个问题,一个是公共的,一个是私有的:

#include <stdio.h>
#include <stdlib.h>

struct private_foo {
    int* val1;
    int* val2;
    int* val3;
};

struct public_foo {
    int const * const val1;
    int const * const val2;
    int const * const val3;
};


void fn( struct public_foo * obj )
{
    int local;
    *(obj->val1) = 20; // compile error
    obj->val1 = &local; // compile error
}

int main(int argc, char* argv[])
{
    // I need to be able to set foo and pass its value in as const into a function
    struct private_foo stoben;
    stoben.val1 = malloc(sizeof(int));
    if (!stoben.val1) { return -1; }
    *(stoben.val1) = 0;
    printf("%d", *(stoben.val1) );
    fn( (struct public_foo *) &stoben );
    printf("%d", *(stoben.val1) );
    free(stoben.val1);
    return 0;
}

When I try to compile the above w/ GCC, I get the following compiler errors, since I'm trying to modify read-only memory:

当我尝试编译上面的w / GCC时,我得到以下编译器错误,因为我正在尝试修改只读内存:

temp.c: In function ‘fn’:
temp.c:20: error: assignment of read-only location
temp.c:21: error: assignment of read-only member ‘val1’

#3


2  

You really can't. A const foo specifies that the members inside are const, that is, they are constant pointers to integers, not pointers to constant integers.

你真的不能。 const foo指定里面的成员是const,也就是说,它们是整数的常量指针,而不是指向常量整数的指针。

The proper solution to this would be via encapsulation, hiding these members and providing a public interface. A practical solution, should you be forbidden to modify the struct foo, would be through private inheritance:

对此的正确解决方案是通过封装,隐藏这些成员并提供公共接口。一个实用的解决方案,如果你被禁止修改struct foo,将通过私有继承:

struct foo {
    int* val1;
    int* val2;
    int* val3;
};

struct constFoo : private foo {
public:
   const int* getVal1() { return val1; }
   const int* getVal2() { return val2; }
   const int* getVal3() { return val3; }
};

Of course, you would need to create the appropriate constructors, etc., so that the original foo can be set up.

当然,您需要创建适当的构造函数等,以便可以设置原始foo。