From: AY on
On Jul 29, 11:10 am, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
wrote:
> On 29 Jul., 15:48, AY <techreposit...(a)gmail.com> wrote:
>
> > This is only for my understanding... I know most of the code in here
> > is wrong. But I was trying out something and am trying to make some
> > sense out of it.. the code is as follows:
>
> First question: Which compiler (including version)
> are you using?
Compiler is gcc version 4.4.3 ( Ubuntu OS )
>
> > int main( void )
> > {>
> > const char* ptrCh = new char[50];
>
> This allocates an array of 50 char characters via operator new[].
> The memory has so-called dynamic storage duration. The contract
> is, that such memory must be released via delete[].
>
> ptrCh is declared as a pointer to const char. This means that
> we can change the contents of ptrCh (i.e. we can assign
> a new address), but we cannot change the pointee
> (i.e. the memory that ptrCh is pointing to) *via* ptrCh.
>
> > ptrCh = "ABCDE";
>
> This is syntactically well-formed, because ptrCh is a pointer
> that can be reassigned. But this assignment is semantically
> wrong, because ptrCh now points to memory that has *not*
> been allocated via operator new[]. Every string literal has *static*
> storage duration and must not be freed by the user.
>
> To be more specific: Above reassignment is OK, unless
> you attempt to provide the pointer pointing to memory
> of non-dynamic storage duration to the deallocation
> function operator delete[].
>
> > // If I'm allowed to allocate memory for *ptrCh in the
> > heap .. Why am I not allowed to delete?
> > //delete [] ptrCh;
>
> Because the memory that ptrCh is currently pointing to does
> not have dynamic storage duration. As an example: The situation
> you are describing here is not much different than this variation:
>
> int main() {
> int i = 12; // Variable i has automatic storage duration
> const int* pi = &i; // OK; pi points to the memory that i refers to.
> delete[] pi; // Not OK, because pi does not point to memory of
> // dynamic storage duration => Undefined behaviour!
>
> }
> > I have read that ' const char* ptr ' means ptr can point to anything
> > but what it points to remains constant.
>
> This is incorrect. The meaning is, that any code that attempts
> to change what ptr points to, is ill-formed. This is *no* dynamic
> memory protection! It is just a static compiler "shield".
> You can also use explicit means (e.g. via const_cast) to let
> the compiler accept this const violation but you are running
> into undefined behaviour, when the actual memory was const
> and after the cast you were trying to modify the memory.
>
> > My Qns:
>
> > 1. Does it mean - In the above code ptrCh is allocated 50 bytes of
> > memory and is it constant?
>
> ptrCh gets at least 50 bytes of memory with dynamic storage
> duration. This memory returned from the operator *is* mutable,
> i.e. you can change what it points to, but you are assigning it
> to a pointer to const, which means that the compiler will statically
> reject any attempt to change the memory via ptrCh. It would be
> possible to reassign the memory to a mutable pointer, though:
>
> char* p = const_cast<char*>(ptrCh);
> p[0] = 'a';
>
> Both lines are well-formed and well-defined, *because* the actual
> memory area is *not* const.
>
> > 2. Would ptrCh save " ABCDE" in the allocated space in the heap -
> > ( Isn't it only an assignment ) ?
>
> No. The meaning is, that you reassign the pointer value of ptrCh:
> It points now to the memory that the array " ABCDE" refers to.>From a
beginners p.o.v. this is a very curious effect, because
>
> the compiler *implicitly* converts the array to a pointer! Welcome
> in the world of C(++)!
>
> If you want to copy the contents from the memory " ABCDE"
> you may use strcpy:
>
> #include <string.h>
>
> int main() {
> char* ptrCh = new char[50];
> strcpy(ptrCh, " ABCDE");
> // ... Do something with ptrCh
> delete[] ptrCh;
>
> }
>
> Note that I did remove the const qualifier from
> ptrCh. If I would not have done this, the compiler
> would reject the following line (using strcpy),
> because strcpy requires a pointer to non-const
> char. This is reasonable, because it will attempt
> to copy soemthing into it.
>
> > 3. If the compiler allows me to allocate memory using new why am I not
> > allowed to delete?
>
> It is OK to do that (in fact you should do that, because otherwise
> you can easily run into memory leaks), but you are required to
> assign a pointer to delete[] that points to memory allocated
> from new[]. In your example you did not do that: You were
> providing memory of static storage duration to that operator.
>
> > 4. The most important qn.. I know there are other methods to handle
> > strings in C++ - like string class, RWCString ( Rogue Wave ) etc.
>
> I don't think, that it is necessary to use proprietary types.
> The most simple solution (and probably the recommended
> one) is to use std::string instead:
>
> #include <string>
> #include <iostream>
>
> int main()
> {
> using namespace std;
> string s = "ABCDE";
> cout<<" ptrCh = " <<ptrCh<<endl;
>
> }
>
> No allocation - no deallocation - std;;string is aleady managing
> this correctly for you.
>
> > Assuming if in some circumstance you are required to create an array
> > of char's lets say 2048 char's. What is the best approach that a
> > programmer like you would do in C++. Please note you are not allowed
> > to use std::string or anything only some form of char
>
> May I ask, why std::string is not allowed?
- Frankly, there is no convincing argument. It was only for my
understanding of char array manipulation better that I wanted to
emphasize that there is no other option apart from using char arrays
in one form or the other..

To be more exact, I am trying to understand the importance of each of
three and the issues with each of them..
>
> > Would you create a
> > 1. char testArray[2048] = "blah blah ..." ;
> > 2. char *testArray = new char[2048]; strcpy(testArray,
> > "blah blah ....");
> > 3. char *testArray = "blah blah .....";
>
> > Apologizing in advance if it sounds more of a C Qn..
>
> First, I would like to understand the reasons why std::string
> is a no go - there may be false assumptions behind that
> argument.
>
> Second, if the arguments are convincing (not to use std::string),
> I would use std::unique_ptr<char[]>, if my compiler supports
> this type (Try header <memory>). This class takes responsibility
> for the memory management.
>

THANK YOU SO MUCH DAN ! I always have some or the other issue with one
or the other forms of char manipulation.

Just wanted to fix it once and for all. Make it crystal clear for
myself.

Your detailed explanation is Invaluable !

Thank You DAN !


> HTH & Greetings from Bremen,
>
> Daniel Kr�gler
>


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 29 Jul., 17:10, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
wrote:
> On 29 Jul., 15:48, AY <techreposit...(a)gmail.com> wrote:
>
> > I have read that ' const char* ptr ' means ptr can point to anything
> > but what it points to remains constant.
>
> This is incorrect. The meaning is, that any code that attempts
> to change what ptr points to, is ill-formed.

To prevent a misunderstanding (Note the insertion):

The meaning is, that any code that attempts
to change what ptr points to *via ptr*, is ill-formed.

> > 4. The most important qn.. I know there are other methods to handle
> > strings in C++ - like string class, RWCString ( Rogue Wave ) etc.
>
> I don't think, that it is necessary to use proprietary types.
> The most simple solution (and probably the recommended
> one) is to use std::string instead:
>
> #include <string>
> #include <iostream>
>
> int main()
> {
> using namespace std;
> string s = "ABCDE";
> cout<<" ptrCh = " <<ptrCh<<endl;

Oops, this line should be:

cout<< " ptrCh = " << s <<endl;

and if we want to bring the output in sync
to what our code wants we better write:

cout<< " s = " << s <<endl;

HTH & Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 29 Jul., 17:10, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
wrote:
> First, I would like to understand the reasons why std::string
> is a no go - there may be false assumptions behind that
> argument.
>
> Second, if the arguments are convincing (not to use std::string),
> I would use std::unique_ptr<char[]>, if my compiler supports
> this type (Try header <memory>). This class takes responsibility
> for the memory management.

Another very reasonable replacement would be to
use std::vector<char> - don't ask me, why I didn't
suggest that in the first place ;-)

My personal guide-line would be: Use std::string, if
possible, or use std::vector<char> as alternative.
The latter is useful, if you do things with the
character sequence that is not really related to
"strings" or if some API constraints forbid
std::string, but std::string *is* the natural
solution for dynamic strings in C++.

HTH & Greetings from Bremen,

Daniel Kr�gler



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel T. on
AY <techrepository(a)gmail.com> wrote:

[snipped the other questions which seemed to be answered adequately. I'm
answering #4 because it is an opinion question.]

> 4. The most important qn.. I know there are other methods to handle
> strings in C++ - like string class, RWCString ( Rogue Wave ) etc.
>
> Assuming if in some circumstance you are required to create an array
> of char's lets say 2048 char's. What is the best approach that a
> programmer like you would do in C++. Please note you are not allowed
> to use std::string or anything only some form of char

I would make a class that does what I need. At minimum, I would support
the Container interface (http://www.sgi.com/tech/stl/Container.html). I
would support other C++ concepts if they were necessary to solve the
problem at hand.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: John Shaw on
> 1. Does it mean - In the above code ptrCh is allocated 50 bytes of
> memory and is it constant?

No. What it means is that storage for 50 characters (char) has been
allocated and the address it has been assigned to ptrCh.

Note: sizeof(char) is implementation depended. Although I have never
used an implementation where it was not a byte.

{ Mod factoid: sizeof(char) is always 1. -mod/sk }

const char* ptrCh = address of allocated memory;

Note: 'char const* ptrCh' is equivalent to the above.

The 'const' before the '*' (ignore the 'char' for the moment) tells
the compiler that the locations pointed to by ptrCh is read only.

PtrCh[0] = 'A'; // Error: you are trying to overwrite read-only memory

Therefor, you need to remove the 'const' modifier from the declaration
of ptrCh.

> 2. Would ptrCh save " ABCDE" in the allocated space in the heap -
> ( Isn't it only an assignment ) ?

No.You have reassigned ptrCh to the address of the static string
�ABCDE�. It is an assignment, but it is an assignment of the address
of the string and not an instruction to copy the string into the
memory block you allocated earlier.

ptrCh = address 1; // assigns address allocated with new char[50]
ptrCh = address 2; // reassigns to address of static string �ABCDE�

> 3. If the compiler allows me to allocate memory using new why am I not
> allowed to delete?

Because you are not trying to delete the memory allocated with
'new' (address 1 above), you are trying to delete the address of the
static string �ABCDE� (address 2 above).

delete [] ptrCh; // Error: trying to delete memory stored at 'address
2'

> 4. The most important qn.. I know there are other methods to handle
> strings in C++ - like string class, RWCString ( Rogue Wave ) etc.
>
> Assuming ... What is the best approach that a
> programmer like you would do in C++. Please note you are not allowed
> to use std::string or anything only some form of char

That depends:

A) How large the array needs to be.

If it requires a very large array, then you want to allocate it using
'new', because placing it on the stack is not practical and may not be
possible without stack over-runs.

char* ptrCh = new char[very large value];

Otherwise you can just declare a local (C-style) array of the given
size.

char chArray[2048];


B) Do you know the required size of the array before hand or is it
given at run-time.

This is the same as (A) above with the exception that if you do not
know the size until run-time, then you have no choice but to allocate
it with 'new'.

void some_func(size_t nSize)
{
char* ptrCh new char[nSize];
� // do something
delete [] ptrCh;
}

C) How are you going to use it.

This is actually the most important part. In your example, it is used
locally and you can apply either (A) or (B) above. But if it is going
to be created in a function and returned as 'char*' or 'const char*',
then it must either be allocated using 'new' or declared as 'static'.
The reason for this is that an array, or any variable for that matter,
placed on the stack, no longer exists after the function returns (it
is out of scope).

char* get_array_1()
{
static char a[2048];
return a; // OK: array is a global static array
}
char* get_array_2()
{
return new char[2048]; // OK: array has been allocated on the heap
// REM: the user is responsible for calling delete [] after usage
}
char* get_array_3()
{
char a[2048];
return a; // Error: this is a local array � allocated on the stack
} // The array is out of scope (popped off stack) and no longer
exists.


Final notes:

Avoid using 'new' if you can; otherwise it is better to wrap the
allocation in a class that deletes it in the destructor, unless you
have a very good reason not to.

If you are allowed to use the STL, then by all means use it.
If you need a 'char' string; use std::string template.
If you need an array; use std::vector<your type>.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]