Understanding char* - C++ - c++

I am writing a code in C++ right now, and I have a dilemma.
EDIT: I added the class relevant definition
_fullName is defined in the class as a private dm(char _fullName)
my class contains the getter method below:
char* getFullName() const { return this->_fullName; }
However, I had in the past cases in which I returned char* with const(const char*)
I can change the getter method to this one:
const char* getFullName() const { return this->_fullName; }
Both versions are compiling but I don't know how to choose.
I would take the second version, but I wonder Why even the version without the const is compiling? shouldn't it give an error when I remove the const keyword, because the function is a CONST member function and therefore the dms are const as well and cannot be returned without the const keyword???
This is the class relevant definition:
class Professional
{
private:
char* _ID;
char* _fullName;
int _age;
char* _profession;
}

First understand what const attached to a member function means. It determines the const-ness of the implicit this used for the member. Given this:
struct S
{
char value[10];
const char *mfn() const { return value; }
};
within the confines of mfn the implicit this is const S *. Furthermore, all references to members obtained therein are also const. In this case, that means value as an expression representation is const char (&)[10] before any further conversion are attached therein.
That's important.
In the correct posted example above there is an automatic conversion to temporary pointer, since const char(&)[10] converts to const char* without objection. However, the following will fail:
struct S
{
char value[10];
char *mfn() const { return value; }
};
The reason this will fail is simply because there is no conversion possible. value, remember, is const char (&)[10], and can only implicitly convert to const char*.
But how could it succeed? Well, consider this:
struct S
{
char *ptr;
char *mfn() const { return ptr; }
};
This will work. The reason is subtle, but obvious once you think about it. ptr is a char*. The attachment of const to this makes that char * const&, not const char *& (there is a difference; the former is a reference to a non-mutable pointer to mutable data, the latter is a reference to a mutable pointer to non-mutable data). Since return ptr is not mutating ptr (or anything else in the object), it is viable as a result.
In short, in your case it works because the pointer you are returning isn't via some implicit conversion from a const underlayment; it's just a value.

You have a few things going on here, in your example of the int num member this is not the same as a char * member.
lets expand your example a bit:
class Professional
{
int* func() const
{
return &myInt; // Fails because it returns a reference to a member variable
}
char* func() const
{
return &myChar; // Fails because it returns a reference to a member variable
}
int* func() const
{
return pInt; // ok because it returns a COPY of the member pointer
}
char* func() const
{
return pChar; // ok because it returns a COPY of the member pointer
}
int myInt;
char myChar;
int *pInt;
char *pChar;
Note: the two pointers getting returned by copy are ok. Its the pointers that are copies not the thing being pointed to. The memory that is pointed to is nothing to do with this class.
As to an answer to your question: there is a rule of thumb that is to apply const as much as possible - this helps to show other users your intent and gains benefits from compiler warnings / errors if a user tries to use your class in a way you did not intend. So in this case pass back a const char *.
Note: See this answer for more specific details here: What is the difference between const int*, const int * const, and int const *?

Related

C++ Difference between const positioning

I'm struggling to get my head around the differences between the various places you can put 'const' on a function declaration in c++.
What is the difference between const at the beginning:
const int MyClass::showName(string id){
...
}
And const at the end like:
int MyClass::showName(string id) const{
...
}
Also, what is the result of having const both at the beginning and at the end like this:
const int MyClass::showName(string id) const{
...
}
const int MyClass::showName(string id) returns a const int object. So the calling code can not change the returned int. If the calling code is like const int a = m.showName("id"); a = 10; then it will be marked as a compiler error. However, as noted by #David Heffernan below, since the integer is returned by copy the calling code is not obliged to use const int. It can very well declare int as the return type and modify it. Since the object is returned by copy, it doesn't make much sense to declare the return type as const int.
int MyClass::showName(string id) const tells that the method showName is a const member function. A const member function is the one which does not modify any member variables of the class (unless they are marked as mutable). So if you have member variable int m_a in class MyClass and if you try to do m_a = 10; inside showName you will get a compiler error.
Third is the combination of the above two cases.
The const attached to the return value applies to the return value. Since the return value is copied it's a pointless declaration and it makes no difference whether or not you include it.
The const after the parameter list means that the function does not modify any state of the object that is not marked as mutable. This is a const member function and if you have a const object the compiler will not allow you to call non-const member functions on a const object.
There is no interaction between these two uses of const - they are completely independent constructs
The difference is that the const applies to different things.
This says that showName returns a constant int value -- one that is immutable. Of course since the int is returned by value the presence of const here does not play any role.
const int MyClass::showName(string id)
And this says that showName does not modify the observable state of MyClass (technically: it does not modify any member that is not declared mutable), and therefore you are allowed to call it on a value of type const MyClass.
int MyClass::showName(string id) const
If you use both consts then both of the above apply.
Questions like this tend to strengthen my resolve to follow the advice of Dan Saks as outlined in this "Conversations with a Guru" article: http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835 .
In particular it deals with how the placement of const changes things. (*) I realize that I am extremely unlikely to convert anyone from writing const int ... to int const ..., but that said, there is one reason I prefer to do the latter.
(*) incuding a note that swapping the const with the type declaration at the very start is the one change that has no effect.
It makes for very easy readability, because for any instance of the word
const in a declaration, everything to the left of it is the type of what is const, and everything to the right is what actually is const.
Consider a declaration like:
int const * * const pointerToPointer;
The first const states that the integers at the end of the pointer chain are const, and they are to be found at * * const pointerToPointer. Meanwhile the second one states that an object of type pointer to pointer to const int is also const and that this object is pointerToPointer.
In the OP's case:
int const MyClass::showName(string id){
...
}
The type of what is const is int, and what is const is the return value from the function.
Meanwhile:
int MyClass::showName(string id) const {
...
}
Here the type of what is const is function(string) returning int, and what is const is the function itself, i.e. the function body.

What would be an use case for a function returning a const pointer (int * const, for example)?

The title is self explanatory, but I'll give an example anyways.
int sum(int a, int b){
return a + b;
}
We could rewrite it as
int sum(const int a, const int b){
return a + b;
}
But what about returning a const int? Is it useful in any way?
const int sum(const int a, const int b){
return a + b;
}
The caller will have to copy the const return to a const lvalue. Is this too restrictive? Do you know any use cases where this could be a good design choice?
Ok, I wasn't clear at the question body. Think about a sum function that works similar to assembly add:
int *sum(int *a, int b){
*a += b;
return a;
}
Add the const's to the params:
int *sum(int * const a, const int b){
*a += b;
return a;
}
What about making the return const too? Is there a reason for this?
There are a lot of situations where you may return a const pointer or a const object. I can't imagine any real situation where you want to return a primitive type as const.
I'm not sure what's your question, in the title your' talking about int* const but in the code example you have a const int.
Some examples (in C++) follows for different combinations of const and T*.
Pointer to const (primitive type)
const int* someFuncion();
You have a pointer to a constant, it means you can change the pointer but you can't change the pointed object/value. Please note that someFunction() must not return a pointer (const or not) to a stack allocated variable. I assume the pointer is valid. For example:
const int* value = someFunction();
// Next line is valid, value will hold a new pointer
value = anotherFunction();
// Next line is not valid, pointed value cannot be changed
*value = 10;
Pointer to const (object)
const T* someFunction();
You have a pointer to a constant. It means you can change the pointer to point to another object but you can't change the pointed object state. This doesn't mean you can't use that object, only that the object is const then you can use only its methods marked as const, read its fields and write its mutable fields. A constant method is defined as:
void method() const;
It can have any return type and any parameter the point is that it's marked with the const modifier. It means that it won't change the object state (again with the exclusion of mutable objects).
Now an example, with T declared as:
class T
{
public:
void dump() const
{
// Dump the value to console, for example
}
void increaseValue()
{
++m_value;
}
private:
int m_value;
};
Imagine to write following code:
const T* value = someMethod();
// Next line is valid, value will hold a new pointer
value = anotherMethod();
// Next line is not valid, we cannot change the object state
value->increaseValue();
// Next line is valid, we do not change the object state
value->dump();
Constant pointer (primitive type)
int* const someFunction();
You have a constant pointer, it means you can change the pointed value but you cannot assign another memory location to the pointer itself. For example:
int* const value = someFunction();
// Next line is not valid, value cannot be changed
value = anotherFunction();
// Next line is valid, you can change the variable pointed by value
*value = 10;
Constant pointer (object)
T* const someFunction();
You have a constant pointer, it means you can change the pointed object state but you cannot assign another memory location to the pointer itself. For example:
T* const value = someFunction();
// Next line is not valid, value cannot be changed
value = anotherFunction();
// Next lines are both valid, we can do whatever we want with the object
value->increaseValue();
value->dump();
Constant pointer to a constant
const int* const someFunction();
This is the mix of previous declarations. All (restrictive) rules described above are valid. It means you can't change the pointer and you can't change the pointed value.
Notes
The const modifier is not restricted to be used to pointers and functions return value. For example:
// PI value cannot be changed
const int PI = 3.14f;
// I have a pointer to a constant value
const* int pPI = Π
// I have a constant pointer to a constant value, note that
const* int const pPI2 = Π
Remember that the const modifier can always be removed using a C-style cast or a const_cast.
Conclusions
So, going back to your question, is it useful a function with a const int return value?
If it's a pointer my answer is yes, even if it can be removed with a cast: the purpose of const is to communicate intentions (saving you from stupid errors hard to find) so more your function communicates and better it'll be used. Updating this from your last example my answer is yes, use const wherever appliable. Who will call your code will thank you (and you'll do it with yourself).
If it's just a const int (or another primitive type) it may be very rare you have to write something like that. Very often they're just intermediate results of a long calculation then it's useless to declare them as const (primitive types won't change but will be combined to create a new value). Note, however, that if it make some sense to declare them as const then you should do it. I guess it's more common to see a constant primitive type declared as local variable (again to be sure it won't be changed by mistake). For example:
// This local variable cannot be modified
const int rate = (calculateX() + calculateY()) / calculateRateFactor();
Or in functions, why not? If you always use this rule (const if shouldn't be changed) you'll see on-the-fly when a parameter isn't const then you'll understand you'll modify it somewhere (maybe with a small, hidden, pretty ++ at the most right character of your screen).
// With this prototype I'm sure I won't change a or b by mistake inside
// the function body.
int someFunction(const int a, const int b);
For objects I think it's even more common to use the const modifier (because a const T return type makes sense very often), for example:
// This object cannot be changed, just moved all around
const order* getNextOrderToStore();
Topic isn't ended, of course, because of aliases, mutables, operators overloading and the differences between C and C++...
I can only see this as a good thing as a statement of intent.
Something more in the sense of - if you get this value, you shouldn't need to change it, more than don't change this value.
This actually accomplishes nothing other than intent, as you're able to change the value anyway: http://ideone.com/Mf8Ge
No, I see few situations where this would be useful, as it really accomplishes nothing, and it restricts what the caller can do with the return value.
The caller will have to copy the const return to a const lvalue.
No, it won't at all. In fact, it might not ever copy it. Or it might copy it to a mutable lvalue.
There is no sense in const rvalues, there never has been, and there never will be.

functions with const arguments Overloading ( Follow up)

This is a follow up of the Previous Question
It got really complicated so I am starting a new thread to make my point clearer.( Didnt want to delete the previous thread because the other guys who gave valuable feedback dont not loose the reputation points they gained)
Updated Code: (Complies and Works)
#include <iostream>
using std::cout;
class Test {
public:
Test(){ }
int foo (const int) const;
int foo (int );
};
int main ()
{
Test obj;
int variable=0;
int output;
do{
output=obj.foo(3); // Call the const function
cout<<"output::"<<output<<std::endl;
output=obj.foo(variable); // Want to make it call the non const function
cout<<"output::"<<output<<std::endl;
variable++;
usleep (2000000);
}while(1);
}
int Test::foo(int a)
{
cout<<"NON CONST"<<std::endl;
a++;
return a;
}
int Test::foo (const int a) const
{
cout<<"CONST"<<std::endl;
return a;
}
Output (I get):
NON CONST
output::4
NON CONST
output::1
NON CONST
output::4
NON CONST
output::2
NON CONST
output::4
NON CONST
output::3
NON CONST
output::4
NON CONST
output::4
NON CONST
output::4
NON CONST
output::5
Output (I desired/had in mind)
CONST
output::3
NON CONST
output::1
CONST
output::3
NON CONST
output::2
CONST
output::3
NON CONST
output::3
CONST
output::3
NON CONST
output::4
CONST
output::3
NON CONST
output::5
Hope I have presented my question better. I know other ways to do it. but is this possible.
In C++, the function signatures
int Test::foo (const int a) const
and
int Test::foo (int a) const
are considered to be complete identical.
The reason that the const on the parameter is disregarded is because it can not affect the caller in any way. As the parameter is passed by value, a copy is made of the value provided by the caller. To the caller, it does not matter in any way if the called function can change that copy or not.
For this reason, C++ ignores a top-level const-qualification on function parameters (top-level const can not occur if passing a reference), and goes even as far that int foo(int); is considered a correct prototype for the function
int foo(const int)
{
/* ... */
}
In short, it is impossible in C++ to overload a function on the constness of (value) function parameters.
To get the output you want, you could consider using a non-const reference parameter for your non-const overload.
The call of const (or non-const) function doesn't depend of the constness of the parameters but only of the constness of the called object (in our case obj). Overload needs different type and (non-const const) are not, so I don't think you can overload as you are doing it. (that work because you are defining a const and a non-const methods but that's not overloading.)
To persuade yourself, try to remove the const at the end of your declaration to see if you are allowed to declare
int foo(int a);
int foo(const int a);
You'll get an error.
In the second case you think foo is expecting a const int as argument but not. const is tied to a not to int. So what it says is foo expect an int, you could refer it using a and that will be const : you are not allowed to modify a. That's why the const (of a parameter) doesn't appear in the function signature (that would be different for a reference).
The const outside the function refers to object called , so that's part of the signature
int foo(int a); # type => int (Test::*)(int)
int foo(const int a) const; # => int (const Test::*)(int)
int foo(const int a) ; # => int (Test::*)(int)
int foo(int a) const; # => int (const Test::*)(int)
(I'm not 100% sure about the type syntax , so don't comment on it, that's just to give an idea)
As you can see the const get removed with a. You can also write it int const a, even if not the standard way to do it, it's perfectly legal.
By the way , your code will never do what you are expected, you should use a reference to an int to modify it
int Test::foo(int &a) ...
Okay, this is how it works:
When you call a function, the value of the parameters are passed to the function. If you pass a value, then this value will be what the function gets. If you pass a pointer, then your function will get a pointer.
When your function receives the argument, all it sees is an integer value. It cannot determine where this value came from, and cannot be static or non static. These properties belong to pointers, which indicate whether or not you can change the value pointed to by the pointers, not the pointers themselves.
Just for good measure, all these function calls look IDENTICAL to the function that recieves them:
int i=1;
int* b = new int;
*b = 4;
func(5);
func(3+2);
func(i+4);
func(*b+1);
So to answer your question, what you are doing is not possible.
EDIT: To change the variable, overload the function with an int, and an int pointer. By passing the address of an int value to the function, your function can change it.
Yep, I can't make it call the const version - unless I do this:
const Test obj2;
output=obj2.foo(3); // Call the const function
No matter what parameter is passed in, if it can call the non-const, it will. If you have a const object, it calls the const version of the function.
Interesting.
Just a clarification. However, we are allowed to overload pointers with and without const arguments in functions, right?
As in,
int Test::foo (const int* a);
int Test::foo (int* a);
How is this different?
Convert you const int to a string, overload your foo with a string and convert back...
Feel free to destroy my answer and the comments.

Const correctness: const char const * const GetName const (//stuff);

Labelled as homework because this was a question on a midterm I wrote that I don't understand the answer to. I was asked to explain the purpose of each const in the following statement:
const char const * const GetName() const { return m_name; };
So, what is the explanation for each of these consts?
Take them from the right. The one before the ; tells the client this is a design level const i.e. it does not alter the state of the object. (Think of this as a read-only method.)
Okay, now the return value:
const char const *const
This is a constant pointer to okay ... here we go boom! You have an extra const -- a syntax error. The following are equivalent: const T or T const. If you take out a const you get a constant pointer to a constant characters. Does that help?
You have one more const than is syntactically allowed, that code would not compile. Remove the "const" after "char" and before the "*". Also, the last const must come before the function body. It helps to read things like this from right to left.
const char * const GetName() const { return m_name; };
You have a const function (i.e., the function does not alter the state of the class.), which returns a const pointer to a const char.
(1)const char (2)const * (3)const GetName() { return m_name; } (4)const;
The contents of char array is const. This is good when you return pointer of the object member. Since you give pointer to your member for 3rd party, you want to prevent it to be changed from outside.
This form is not used frequently and essentially same as (1)
Our pointer to char array is const, so you can not change where the pointer points too.
it qualifies the GetName() intself, meaning that the method thus not change the class it applied too. Thus it can be called for const object of this type only.
This form typically used as GetName(...) const.
As already mentioned in another answers the trick to "remember" it it read from right to left:
const T * - pointer to const T
T * const - const pointer to T
Edit: Looks like I incorrectly pasted the code into Comeau, or it was edited in the original answer to be correct. In either case I'm preserving the answer below as if the code were incorrect.
Comeau online compiler gives these results:
"ComeauTest.c", line 4: error: type
qualifier specified more than once
const char const * const GetName() {
return m_name; } const;
^
"ComeauTest.c", line 4: warning: type
qualifier on return type is
meaningless const char const * const
GetName() { return m_name; } const;
^
"ComeauTest.c", line 4: error:
declaration does not declare anything
const char const * const GetName() {
return m_name; } const;
What this means is that your statement is malformed.
const char const * const GetName() { return m_name; } const;
The first and second consts mean the same thing. You can't specify the same qualifier more than once so one of these would have to be removed for the code to compile. Both of these consts specify that the values pointed to by the pointer returned by GetName cannot be modified, making code like this invalid:
const char* name = c.GetName();
name[0] = 'a';
The third const specifies that the pointer returned by GetName() itself cannot be modified, but as Comeau points out, this doesn't accomplish anything on a return value because the return value is a copy of the pointer rather than the pointer itself, and can be assigned to a non-const pointer.
The fourth const is misplaced, it should be between GetName and the function body like this:
const char* GetName() const { return m.name; }
This const specifies that no members of the class will be modified during the execution of GetName. Assuming that GetName a member of the class Person, this code would be allowed:
const Person& p;
p.GetName();
Without this const, the above code would fail.
It is possible that you missed "*" symbol before second const keyword.
const char * const * const GetName() const { return m_name; };
So it means that the function returns constant pointer to constant pointer to constant character.
last const:
Function does not change the privates of the class
one after last const:
It's a constant pointer (i.e. the place it points to is constant)
second const:
The function returns a const char (i.e. the content of the char is constant)
First:
No idea?
So to be complete:
The function returns a constant pointer (always same location) to a constant char(always same content) and the function does not modify the state of the class.
const(1) char const(2) * const GetName() { return m_name; } const(3);
const char * const result = aaa.GetNAme();
3 - const method, not allowed to change members nor call any non-const methods.
1 - does not allow to modify inside the pointer, i.e. *result = ..
2 - does not allow to move the pointer, i.e. result = NULL
Given:
const char const * const GetName() const { return m_name; };
The first and second const are equivalent, but only one of them is allowed -- i.e. you can put const before or after the type (char in this case) but only one or the other, not both. Either, however, says that the characters pointed to by the pointer cannot be written to.
The const after the '*' means the pointer returned by the function cannot itself be modified. This is rarely seen on a return type -- what you're returning is a value, which can't be modified in any case (it's normally just assigned to some variable). This can, however, be meaningful in other contexts.
The third const is only allowed on a member function. It says that when this function is called, the this pointer that's received will be a T const * const rather than a T * const, so the member function can only modify static or mutable members of the object, and if it invokes other member functions, they must be const as well. There is, however, a caveat, that it can also cast away the const'ness, in which case it can modify what it sees fit (with the further caveat that if the object was originally defined as const, rather than just having a const pointer to a normal (non-const) object, the results will be undefined).

Why does this const member function allow a member variable to be modified?

class String
{
private:
char* rep;
public:
String (const char*);
void toUpper() const;
};
String :: String (const char* s)
{
rep = new char [strlen(s)+1];
strcpy (rep, s);
}
void String :: toUpper () const
{
for (int i = 0; rep [i]; i++)
rep[i] = toupper(rep[i]);
}
int main ()
{
const String lower ("lower");
lower.toUpper();
cout << lower << endl;
return 0;
}
A const member function, is a member function that does not mutate its member variables.
const on a member function does not imply const char *. Which would mean that you can't change the data in the address the pointer holds.
Your example does not mutate the member variables themselves.
A const on a member function, will ensure that you treat all of your member variables as const.
That means if you have:
int x;
char c;
char *p;
Then you will have:
const int x;
const char c;
char * const p; //<-- means you cannot change what p points to, but you can change the data p points to
There are 2 types of const pointers. A const member function uses the one I've listed above.
A way to get the error you want:
Try changing:
char * rep;
to:
char rep[1024];
And remove this line:
rep = new char [strlen(s)+1];
It will throw the error you are expecting (can't modify members because of const keyword)
Because there is only 1 type of const array. And that means you cannot modify any of its data.
Now the whole system is actually broken with the following example:
class String
{
private:
char rep2[1024];
char* rep;
...
String :: String (const char* s)
{
rep = rep2;
strcpy (rep, s);
}
So the lesson to learn here is that the const keyword on member functions does not ensure that your object will not change at all.
It only ensures that each member variable will be treated as const. And for pointers, there is a big diff between const char * and char * const.
Most of the time a const member function will mean that the member function will not modify the object itself, but this is not always the case, as the above example shows.
The reason is that you don't change rep. If you would, you would find rep = ...; somewhere in your code. This is the difference between
char*const rep;
and
const char* rep;
In your case, the first one is done if you execute a const member-function: The pointer is const. So, you won't be able to reset the pointer. But you will very well be able to change what the pointer points to.
Now, remember rep[i] = ...; is the same as *(rep + i) = ...;. Thus, what you change is not the pointer, but what the pointer points to. You are allowed, since the pointer is not of the second case type.
Solution
The const meaning you are looking at is physical constness. However, a const member-function means your object is logical const. If a change to some content will change the logical constness of your object, for example if it changes some static variable that your object depends upon, your compiler cannot know that your class now has another logical value. And neither it can know that the logical value changes dependent on what a pointer points to: The compiler doesn't try to check logical constness in a const member function, since it cannot know what those member variables mean. This stuff is termed const-correctness.
Use an object that is not just a reference or a pointer: A const member function will make that object const, and will disallow you to change its content. std::string, as proposed by some, or an array of characters (note that an array will disallow you changing its content, as opposed to just a pointer), would be an appropriate choice.
2.
toUpper() does not change the pointer (which belongs to the class). It only changes the data which rep points to (that do not belong to the class).
However, 'const' is a sort of warranty for the users of your class: if a method is declared const, who uses an instance of your class can expect it won't change when calling the method. My point is, if toUpper() changes the state of a string, don't declare it const, whether C++ allows it or not.
The const qualifier means it will not change any members of the class.
In this case rep is the only member of the class and I see no attempt to modify this member. Anything pointed at or referenced outside the class is not considered as part of the class.
A solution to this problem would be to replace the char* with a std::string.
Then you would only be able to call const members of std::string from within toUpper()
For example (use std::string)
class String
{
std::string rep;
void toUpper() const
{
for (int i = 0; rep [i]; i++)
rep[i] = toupper(rep[i]);
// Can only use const member functions on rep.
// So here we use 'char const& std::string::operator[](size_t) const'
// There is a non const version but we are not allowed to use it
// because this method is const.
// So the return type is 'char const&'
// This can be used in the call to toupper()
// But not on the lhs of the assignemnt statement
}
}
You cannot change the value of something declared as
const char* rep;
or
const char* const rep;
Unfortunately, declaring your member const turns into rep into
char* const rep;
which means, you cannot change the acutal address, but you can change the contents, whereas you cannot change the value.
To make const memebrs respect keep your buffer const, you will need to make rep and array of characters or a string object rather than a character pointer.