简体   繁体   中英

Convert C++ struct members from non-const to const

Is there a simple way to pass a non-const C++ structure (via pointer) into a function, and make sure that the function cannot alter members of the struct?

Ex: A structure is loaded from a config file, which requires the struct to be non-const. But then a pointer to the struct is passed into a function that is not permitted to alter anything.

I've seen this done by creating a second verbatim 'const' copy of the struct, and tediously copying every member. That seems odd. I'm a C# programmer though, so perhaps that is the way it is done in C++...?

In C++ you can pass big objects as reference or pointer both is called "Call by reference" in contrast to "Call by value" where a copy is made. The pointer syntax is inherited by the C language and differs from C++ references.

To make the compiler complain about changes to your object you have to use the const keyword. Sure you can cast the const ness away to change the values anyway, but casting const ness away isn't recommended at all.

Let's assume for the following examples that you have a class BigObject with a public member a which is an integer int .

1. Call by reference (&: reference type):

void function(const BigObject& input)
{
   int a = input.a; /* read from BigObject     */
   input.a = 42;    /* the compiler will fail! */
}

/* call that function */
BigObject input();
function(input); /* no address operator needed */

The const keyword will make the reference & (not the address operator here) refer to data that can't be changed by this reference. If you try that the compiler will fail compiling.

2. Call by reference (*: pointer type):

void function(const BigObject* input)
{
   int a = input->a;  /* read from BigObject     */
   int b = (*input).a /* alternative to ->       */
   input->a = 42;     /* the compiler will fail! */
}

/* call that function */
BigObject input();
function(&input); /* pass address */

The argument is a pointer type which points to data which can't be changed by this pointer. You can also make the pointer constant by using: const BigObject* const input , more explanation about this follows below.


Here are the differences between references and pointers:

  • A pointer needs to be dereferenced, this is done by the dereference (star) operator * or with -> for class/struct members, see code above.
  • Further you have to pass the address of the object using the address operator & to get a pointer.
  • Another difference is, that references can't be NULL they have to be valid, but a pointer can point to NULL .

Placement of const keyword:

The placement of the const keyword decides about what should be constant, the pointer or the object to which the pointer points.
In general there are the following which you can easier remember if you just think of a vertical line going through the * (star). If const is on the left of the * it will apply to the type (object), if it's on the right it will apply to the pointer:

                |
BigObject       *        input /* pointer to BigObject             */
const BigObject *        input /* pointer to constant BigObject    */
BigObject const *        input /* same as before, I don't use this */
BigObject       * const  input /* constant pointer to BigObject    */
                |

which you can also combine to make both constant:

                |
const BigObject * const  input /* constant pointer to constant BigObject */
                |

The placement of the const keyword doesn't matter on references. A reference is always constant (this is implicit and not named explicitly), means it can't reference to another object once it was set. The object is mutable however. This means the const keyword on the right side of & would be redundant and not change anything, just don't use that. You should just differ between:

BigObject&        input /* reference to BigObject           */
const BigObject&  input /* reference to constant BigObject  */
BigObject const & input /* same as before, I don't use this */

The solution is simple: Pass a pointer to const to the function instead (or, perhaps a reference would be more appropriate). The function will not be able to modify the object through the pointer to const.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM