I don't know why this simple code is not working:
int main()
{
const char* c = "ret";
typedef unsigned char GOK_UINT8;
typedef GOK_UINT8* pGOK_UINT8;
const pGOK_UINT8 y = reinterpret_cast<const GOK_UINT8*>(c);
return 0;
}
Can someone tell me why the reinterpret_cast does not work?
Can someone tell me why the reinterpret_cast should not work?
AFAICS, the reinterpret_cast should work fine, but the assignment afterwards should cause an error.
That's because a const GOK_UINT8* is a non-const pointer to const GOK_UINT8 objects, while a const pGOK_UINT8 is a const pointer to non-const objects.
The former protects the object referred to, the latter the pointer referring to the object. If the assignment would be allowed, you could then change the object that the const GOK_UINT8* meant to protect from changing.
Note that typedefed pointers behave strange that way. That's because of the strange declaration syntax of const in (C and thus also in) C++: A const protects the thing to its left, unless there isn't anything, then it protects the thing to its right. So in T const and in T const*, the object of type T is protected, while in T* const the pointer to an object of type T is protected. If you have
typedef T* TPtr;
then TPtr const again makes the pointer const. So does const TPtr. A typedefed pointer either points to const or non-const objects, you can't change that. You can't stuff a const into the vicinity of TPtr and expect that to protect the objects the pointer refers to.
(BTW, this is why STL classes have to define both an iterator and a const_iterator.)
Yep sbi is correct.
Modified your code accordingly,
const char* c = "ret";
typedef unsigned char GOK_UINT8;
typedef const GOK_UINT8* pGOK_UINT8;
pGOK_UINT8 y = reinterpret_cast<const GOK_UINT8*>(c);
printf("%s", y);
Related
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 *?
So Wikipedia tells me (correctly i believe) that to stop the editing of the data of a pointer and the pointer itself that I should do this:
void function(int const * const var)
Is this the same as this function:
void function(const int * const var)
And in that case why is it allowed? Because I know that you cant do this because of duplicate const compile error:
void function(const int const * const var)
I essentially want to do the same with a boost pointer. Would I do this:
void function(const boost::shared_ptr<int> const var)
And how would this affect my ability to loop over say a shared pointer to a vector? Could I do this with that guard:
void function(const boost::shared_ptr<std::vector<int>> const var)
{
for (unsigned int i = 0; i < var->size(); ++i)
{
std::cout << var[i];
}
}
Adition: After Brian's answer
So if I create a a pointer like this:
boost::shared_ptr<vector<int>> lala
And i use it in this function:
function (const boost::shared_ptr<std::vector<const int>> var)
will that work?
Yes, int const * const var is the same as const int * const var. You can put const before or after the type it modifies, for "historical reasons". See http://www.stroustrup.com/bs_faq2.html#constplacement
For a smart pointer object, you indeed cannot do
const boost::shared_ptr<int> const
because both consts modify the same type. Instead, you want
const boost::shared_ptr<const int>
The first const prevents the pointer itself from being modified (i.e., reassigned to point to another int) and the const in the template parameter tells the object's operator* to return a const int&, which prevents modification of the int pointed to.
This does not prevent iteration over a vector or other container in the manner you have described, for the same reason why you can still iterate over a const vector normally.
Edit in response to question edit:
This works:
void f(const boost::shared_ptr<const std::vector<int> > var);
// ...
boost::shared_ptr<vector<int> > lala;
f(lala);
The first const in the parameter doesn't affect parameter passing at all; it only tells the function itself not to modify the parameter. The reason why we can add a const in the template parameter is that a boost::shared_ptr<T> can be initialized from boost:shared_ptr<U> where T and U are not necessarily the same type, as long as U* is implicitly convertible to T*. If T is the same as U except with greater cv-qualification, as in this case, the conversion is possible.
Don't do std::vector<const int>. I'm fairly sure that's not legal. (At least I've gotten multiple screens of compilation errors every time I've tried it.)
const before or after the int is the same so:
int const * var
and
const int * var
are the same and mean the value pointed to cannot be changed
const after the * means that the pointer cannot be reassigned.
If I understand correctly, you'd like to make the vector const. If that's the case the syntax would be this:
void function(const boost::shared_ptr<const std::vector<int>>& var)
The smart pointer is passed by const reference because it's cheaper than passing the smart pointer by value and has the same effect. The object pointed to by the smart pointer is immutable by declaring the type it points to as const.
You've correctly reasoned that const shared_ptr<Foo> doesn't make Foo a const object. This "loophole" is described on wikipedia. Instead, you need to change the pointer type stored by boost::shared_ptr. This can be done in the template argument itself:
void function(const boost::shared_ptr<const std::vector<int>>& var)
boost::shared_ptr has a copy-constructor that allows for a const-type to be copied from a non-const-type. The opposite should not be possible.
Before, or after?
The below two lines are semantically equivalent, both declare a pointer which value cannot be changed, that refers to an int that cannot be changed.
int const * const p1 = ...;
const int * const p2 = ...;
The const keyword binds to whatever is directly to the left, unless there's nothing to the left, in which case it will hug whatever is on the right.
The more const, the better?
typedef boost::shared_ptr<int> shared_int_ptr;
const shared_int_ptr const p3; // ill-formed
The above typedef is provided to make it easier to see that boost::shared_ptr<int> is a single name, and therefore we cannot add const on both sides; duplicate consts are (as you mentioned) not legal C++.
Just applying one wouldn't be sufficient either, since that would make the wrapper const, but not the internal object that it is referring to (the int).
Previously we wrote that boost::shared_ptr should wrap around an int, but since we want to make the wrapped type const, well.. let's wrap the shared_ptr around what we want:
void func (const boost::shared_ptr<const int> foo);
In the above func is not able to modify foo, nor the int referred to by foo.
I have seen const used twice in the declaration of a static array before and now that I am creating my own static array I am wondering why const would be needed twice in some situations.
Does having an array of pointers make a difference?
a. static const TYPE name[5];
b. static const TYPE const name[5];
c. static const TYPE* name[5];
d. static const TYPE* const name[5];
My understanding is that b. is invalid, but if using const twice is valid, what is its purpose?
const TYPE* x;
Means that the thing that x points at is const.
TYPE* const x;
Means that the pointer x is const.
Combining the 2 you get:
const TYPE* const x;
Meaning the pointer and the thing pointed to are both const.
You can apply any cv-qualifier (const or volatile) to any type, including cv-qualified types -- yet not in the same declaration. However, they bind more strongly than any operator, in terms of precedence and can be applied on both sides of the qualified type:
// Let T by any type:
T const tr;
const T tl;
const T const tlr; // only in C
const const const const const T t5; // only in C
typedef const T CT;
CT const tcc; // fine, although CT was already const
declare exactly the same, a constant T. If T already has cv-qualifiers, this doesn't change the meaning of additional qualification.
Now, to the precedence; You can say "I want a pointer to a constant T":
const T (* tp);
which is usually written as
const T* tp;
because the const binds stronger than the * anyway. In the same pattern, you can define a variable that is "constant but points at a mutable T":
T (* const tp) = 0; // must be initialised, because tp is immutable
which is commonly written as
T* const tp = 0;
In the same vein the subscript operator [] is applied -- with the same precedence as in expressions.
In the first code block you have a redundant duplicate const in the second line, which has no effect. (In fact, good compilers will warn you about this.) You're declaring an array of 5 const TYPEs, that's it.
The second code block has two different scenarios: The first line makes an array of five mutable pointers to const TYPEs, while the latter makes an array of five constant pointers to const TYPEs.
Note that you must initialize an array of constants: Since you can't change the values later, it doesn't make sense to define them uninitialized.
Using const twice on a type is illegal in C++ 2003 but legal in C++ 2011 (see 7.1.6.1 [decl.type.cv] paragraph 1: "Redundant cv-qualifications are ignored."). When you used
static const TYPE const name[5];
you made TYPE constant twice. Note, however, that this declaration is illegal in C++ 2011, too, because you need initialize a const object when declaring it. The meaning of
const TYPE
and
TYPE const
is absolutely equivalent: In both cases you make the TYPE object constant. For consistency, I always put the const to the right because every except for the top-level type the const has to be put on the right side (well, unless some coding guideline mandates differently but I'm fighting silly coding guidelines).
When using pointers, thinks become different. There are two types involved: type pointed to type and the pointer. Each one of these can be made const separately:
TYPE const* ptr1(0); // non-const pointer to const TYPE
TYPE* const ptr2(0); // const pointer to non-const TYPE
TYPE const* const ptr3(0); // const pointer to const TYPE
The best way to figure out what is made const is to read the type declaration from right to left. Of course, this assumes to that const qualifiers are put into the right location. You can replace const by volatile or const volatile in the discussion above and the same reasoning applies.
In running this C++ code, I expected the output to be Abc, but, it was FFF, why is that? Isn't name pointing to a constant char?
#include <iostream>
int main()
{
const char* name = "Abc";
name = "FFF";
std::cout<<name<<std::endl;
return 0;
}
Yes, it's pointing to a const char as you say, but it is not a constant pointer. You are changing what you are pointing to, not the contents of what you are pointing to. In other words, the memory holding "Abc" still holds the characters "Abc" after you reassign the pointer.
For a constant pointer, you want const char* const name = "Abc";. In this case, it won't compile since you can't change what the pointer points to.
In general, with const and pointers in C++, you can read the type name from right-to-left to get a feel for what is going on. For example, in the const char* const case, you can read this as "a constant pointer to a character constant". A little weird, but it works.
const char* name = "Abc"; -> Non const pointer-> name, but data (Abc) is constant
name = "FFF" -> changing pointer(name) to point to FFF.
char *p = "Hello"; // non-const pointer,
// non-const data
const char *p = "Hello"; // non-const pointer,
// const data
char * const p = "Hello"; // const pointer,
// non-const data
const char * const p = "Hello"; // const pointer,
// const data
With const char* name = "Abc"; you are telling compiler you will not change the contents of "Abc" using name. However, you are free to change the pointer to point to a different memory location. See this FAQ for details.
It is a known issue with const and English speakers.
The syntax allows both:
const T
T const
and both have the same meaning.
However it becomes complicated once you throw a pointer in the mix:
const T* should be read (const T)*
T const* should be read (T const)*
T* const should be read (T*) const
For that reason I am an adept of always using const on the immediate right of the object. This is more consistent.
Note that the same issue can be found with typedef, let's define typedef T* pointer:
const pointer means T* const, not const T* (as a macro would imply)
pointer const means T* const, like the textual replacement
If you take the habit of putting the const after the name, and not before like an adjective in English, then you won't fall into those traps.
in deed the most correct syntax is
char const * pName;
because const keyword apply namely to the part on the left hand side.
if you want a const poitner to a const char you would write it:
char const * const pName;
and a const pointer to an int;
int * const pInt;
PS: but I still write the const at the begining of the line whenever I can, an anchored habbit ;-)
const char* name = "Abc";
Actually this means, name is a pointer to the const data. Means, it's the data which is const, not the pointer itself. So it's perfectly valid if you write:
name = "FFF"; //ok : changing the pointer
However, the following will not compile:
char * const name = "Abc"; //const pointer to the non-const data!
name = "FFF"; //error: trying to change the pointer itself!
See the compiler error:
prog.cpp:5: error: assignment of
read-only variable ‘name’
See yourself here : http://www.ideone.com/KyNXx
When you declare a variable as
const T* ptr = /*...*/
You are declaring a pointer saying that the object being pointed at, not the pointer, must not change. In other words, it's a "pointer to a T that's const."
If you want to make it impossible to reassign the pointer, you can write
T* const ptr = /*...*/
This is now an immutable pointer to a T, which can be modified.
You can combine these together like this:
const T* const ptr = /*...*/
To get an immutable pointer to an immutable T.
As a fun hint, you can usually determine what parts of a pointer/pointed pair can be modified by reading the type right-to-left. Try that out on the above and see what you get.
First, const is only checked at compilation time. If it compiles, all operations will be done normally at runtime.
In your example, const applies to the content pointed by name. So you are allowed to change the pointer, but not the content.
strcpy(name, "FFF");
would be refused, but not changing the pointer like you did.
The literal strings "Abc" and "FFF" are constant, but name is a variable (pointer to constant data). You have simply changed the variable to point to different constant data.
Moreover while in this case the data was necessarily constant, a pointer to constant data only means that the data cannot be modified by dereferencing that pointer, the data might also be modified directly or through a different pointer. E.g.
int i = 0 ;
const int* p = &i ;
i++ ; // valid
(*p)++ // error.
I can't find much information on const_cast. The only info I could find (on Stack Overflow) is:
The const_cast<>() is used to add/remove const(ness) (or volatile-ness) of a variable.
This makes me nervous. Could using a const_cast cause unexpected behavior? If so, what?
Alternatively, when is it okay to use const_cast?
const_cast is safe only if you're casting a variable that was originally non-const. For example, if you have a function that takes a parameter of a const char *, and you pass in a modifiable char *, it's safe to const_cast that parameter back to a char * and modify it. However, if the original variable was in fact const, then using const_cast will result in undefined behavior.
void func(const char *param, size_t sz, bool modify)
{
if(modify)
strncpy(const_cast<char *>(param), sz, "new string");
printf("param: %s\n", param);
}
...
char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true); // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true); // UNDEFINED BEHAVIOR
I can think of two situations where const_cast is safe and useful (there may be other valid cases).
One is when you have a const instance, reference, or pointer, and you want to pass a pointer or reference to an API that is not const-correct, but that you're CERTAIN won't modify the object. You can const_cast the pointer and pass it to the API, trusting that it won't really change anything. For example:
void log(char* text); // Won't change text -- just const-incorrect
void my_func(const std::string& message)
{
log(const_cast<char*>(&message.c_str()));
}
The other is if you're using an older compiler that doesn't implement 'mutable', and you want to create a class that is logically const but not bitwise const. You can const_cast 'this' within a const method and modify members of your class.
class MyClass
{
char cached_data[10000]; // should be mutable
bool cache_dirty; // should also be mutable
public:
char getData(int index) const
{
if (cache_dirty)
{
MyClass* thisptr = const_cast<MyClass*>(this);
update_cache(thisptr->cached_data);
}
return cached_data[index];
}
};
I find it hard to believe that that's the only information you could find about const_cast. Quoting from the second Google hit:
If you cast away the constness of an
object that has been explicitly
declared as const, and attempt to
modify it, the results are undefined.
However, if you cast away the
constness of an object that has not
been explicitly declared as const, you
can modify it safely.
What Adam says. Another example where const_cast can be helpful:
struct sample {
T& getT() {
return const_cast<T&>(static_cast<const sample*>(this)->getT());
}
const T& getT() const {
/* possibly much code here */
return t;
}
T t;
};
We first add const to the type this points to, then we call the const version of getT, and then we remove const from the return type, which is valid since t must be non-const (otherwise, the non-const version of getT couldn't have been called). This can be very useful if you got a large function body and you want to avoid redundant code.
The short answer is no, it's not safe.
The long answer is that if you know enough to use it, then it should be safe.
When you're casting, what you are essentially saying is, "I know something the compiler doesn't know." In the case of const_cast, what you are saying is, "Even though this method takes in a non-const reference or pointer, I know that it won't change the parameter I pass it."
So if you do actually know what you are claiming to know in using the cast, then it's fine to use it.
You're destroying any chance at thread-safety, if you start modifying things that the compiler thought were const.