I am using c++.
I want to initialize pointer of string. I have been doing it using :
string *strPtr = new string("abcd");
But I don't want to use heap memory. Use somthing like this :
string *strPtr;
// initialize with "abcd"
How can I do it using stack memory?
You can declare a string on the stack and then take the address of it:
std::string str{"abcd"};
std::string* ptr_str = &str;
But I'm sure it would be more convenient for you to handle a reference, a smart pointer, or maybe a std::string_view. Raw pointers should be used in some very specific cases nowadays.
Like this:
string str("abcd");
string *strPtr = &str;
Sometimes you can get away with using alloca() to allocate memory on the stack, you'd need to allocate twice, once for metadata and once for data and then reinterpret_cast...
I'm trying to return a string from a function that does some processing.
I've tried returning it as an rvalue reference and also as an lvalue reference. didn't work :(.
processing function:
std::string processingFunction()
{
std::string str = "";
//processing...
strftime(&str[0], MAX_LENGTH, DATE_FORMAT, tm_STRUCT_ADRRESS);
return str;
}
use of the function:
std::string temp = processingFunction();
if(temp.empty())
{
//stuff
}
When debugging (in VS 2019), I can see the value of temp in the Watch, but temp.empty() always returns 1. Even if I can see that the value is present.
here is a screenshot for tl;dr:
m_bucket_function is the processing function
You define a std::string object and set it to "" (the empty string).
You then use strftime() to copy, as a C-style string, a representation of some time to memory starting at &str[0].
The expression &str[0] (where str is a std::string) does give you access to the initial byte of the data managed by the str::string object -- but it doesn't allocate memory to hold the new value, and it doesn't update the std::string object's internal data (including the length of the string it represents). Your call to strftime() is likely to clobber unallocated memory (undefined behavior).
You need to use strftime() to copy data into a char array, and then copy that data into your str. std::string's assignment operator will then take care of updating the metadata and allocating memory as needed.
There's no problem with returning a std::string by value, as you're doing.
temp.empty() always returns 1
just means the string is empty.
Now that you've posted more code and as #SkyZip comments, the problem lies in:
strftime(&str[0], ...
this gets strftime to overwrite memory by passing it the address of your string.
If you really have to use strftime you can do it like so:
std::string processingFunction()
{
char buff[MAX_LENGTH];
strftime(buff, MAX_LENGTH, DATE_FORMAT, tm_STRUCT_ADRRESS);
//processing...
return std::string(buff);
}
And as #Keith said, you are working with objects here. Not just plain old C data types.
Edit:
Just for reference, here is a similar question:
Current date and time as string
As part of a small program i need to convert a string to a char array. I want to use the strncpy_s() method but I keep getting an assertation saying that the "buffer is too small".
This is what my code looks like:
char* ostr = new char[sizeof(str)+1];
strncpy_s(ostr, sizeof(ostr), str.c_str(), sizeof(ostr));
Hope someone can help me.
The variable str is, it seems, a std::string object. The size of the object is the size of its member variables, which for std::string commonly is a pointer (to the actual string) and variable for the length of the string.
If you want to get the length of the wrapped string you need to use the length function.
Furthermore, there is another problem with your call to strncpy_s: You do sizeof(ostr), which is the size of the pointer, not the size of the memory it points to.
Lastly, if you want to pass a pointer to the string to a C function, then either use str.c_str() directly in the call. Or if the C function needs to modify the string (but not reallocate it) then use e.g. str.data() or &str[0].
If the C function needs to reallocate the data then you can't use new[] to allocate it. You need to use malloc (or possibly strdup if your system have it).
I've appends some elements in my list
std::list<std::string> dirList2;
//Code
dirList2.push_back(findData.cFileName);
copy(dirList2.begin(), dirList2.end(),std::ostream_iterator<std::string> (std::cout,"\n"));
Everything work, i can view this items,
Now i want to assign the first elem of my list to a char* .
Can someone help me please ? i'dont know how to do it
If I understood well what you want then you can do it like this:
const char *s = dirList2.front().c_str();
Be careful, though. The C string which variable s points to is owned by the string object sitting on your list. If the list goes out of scope or you remove the element from your list, then the C string will be released by the std::string's destructor and your s pointer will not be valid.
If you want to manipulate the C string beyond the liftime of the std::string object than you can do sth. like this:
const char *s = strdup(dirList2.front().c_str());
But it's usually better to use std::string instead of raw C pointers, unless you have no choice.
The string object provides a c_str() method which will return a const char *. If you need to modify the string you must also make a copy of the string (IE using strcpy where the source pointer is the one returned by c_str())
For educational purposes, I am using cstrings in some test programs. I would like to shorten strings with a placeholder such as "...".
That is, "Quite a long string" will become "Quite a lo..." if my maximum length is set to 13. Further, I do not want to destroy the original string - the shortened string therefore has to be a copy.
The (static) method below is what I come up with. My question is: Should the class allocating memory for my shortened string also be responsible for freeing it?
What I do now is to store the returned string in a separate "user class" and defer freeing the memory to that user class.
const char* TextHelper::shortenWithPlaceholder(const char* text, size_t newSize) {
char* shortened = new char[newSize+1];
if (newSize <= 3) {
strncpy_s(shortened, newSize+1, ".", newSize);
}
else {
strncpy_s(shortened, newSize+1, text, newSize-3);
strncat_s(shortened, newSize+1, "...", 3);
}
return shortened;
}
The standard approach of functions like this is to have the user pass in a char[] buffer. You see this in functions like sprintf(), for example, which take a destination buffer as a parameter. This allows the caller to be responsible for both allocating and freeing the memory, keeping the whole memory management issue in a single place.
In order to avoid buffer overflows and memory leaks, you should always use C++ classes such as std::string in this case.
Only the very last instance should convert the class into something low level such as char*. This will make your code simple and safe. Just change your code to:
std::string TextHelper::shortenWithPlaceholder(const std::string& text,
size_t newSize) {
return text.substr(0, newSize-3) + "...";
}
When using that function in a C context, you simply use the cstr() method:
some_c_function(shortenWithPlaceholder("abcde", 4).c_str());
That's all!
In general, you should not program in C++ the same way you program in C. It's more appropriate to treat C++ as a really different language.
I've never been happy returning pointers to locally allocated memory. I like to keep a healthy mistrust of anyone calling my function in regard to clean up.
Instead, have you considered accepting a buffer into which you'd copy the shortened string?
eg.
const char* TextHelper::shortenWithPlaceholder(const char* text,
size_t textSize,
char* short_text,
size_t shortSize)
where short_text = buffer to copy shortened string, and shortSize = size of the buffer supplied. You could also continue to return a const char* pointing to short_text as a convenience to the caller (return NULL if shortSize isn't large enough to).
Really you should just use std::string, but if you must, look to the existing library for usage guidance.
In the C standard library, the function that is closest to what you are doing is
char * strncpy ( char * destination, const char * source, size_t num );
So I'd go with this:
const char* TextHelper::shortenWithPlaceholder(
char * destination,
const char * source,
size_t newSize);
The caller is responsible for memory management - this allows the caller to use the stack, or a heap, or a memory mapped file, or whatever source to hold that data. You don't need to document that you used new[] to allocate the memory, and the caller doesn't need to know to use delete[] as opposed to free or delete, or even a lower-level operating system call. Leaving the memory management to the caller is just more flexible, and less error prone.
Returning a pointer to the destination is just a nicety to allow you to do things like this:
char buffer[13];
printf("%s", TextHelper::shortenWithPlaceholder(buffer, source, 12));
The most flexible approach is to return a helper object that wraps the allocated memory, so that the caller doesn't have to worry about it. The class stores a pointer to the memory, and has a copy constructor, an assignment operator and a destructor.
class string_wrapper
{
char *p;
public:
string_wrapper(char *_p) : p(_p) { }
~string_wrapper() { delete[] p; }
const char *c_str() { return p; }
// also copy ctor, assignment
};
// function declaration
string_wrapper TextHelper::shortenWithPlaceholder(const char* text, size_t newSize)
{
// allocate string buffer 'p' somehow...
return string_wrapper(p);
}
// caller
string_wrapper shortened = TextHelper::shortenWithPlaceholder("Something too long", 5);
std::cout << shortened.c_str();
Most real programs use std::string for this purpose.
In your example the caller has no choice but to be responsible for freeing the allocated memory.
This, however, is an error prone idiom to use and I don't recommend using it.
One alternative that allows you to use pretty much the same code is to change shortened to a referenced counted pointer and have the method return that referenced counted pointer instead of a bare pointer.
There are two basic ways that I consider equally common:
a) TextHelper returns the c string and forgets about it. The user has to delete the memory.
b) TextHelper maintains a list of allocated strings and deallocates them when it is destroyed.
Now it depends on your usage pattern. b) seems risky to me: If TextHelper has to deallocate the strings, it should not do so before the user is done working with the shortened string. You probably won't know when this point comes, so you keep the TextHelper alive until the program terminates. This results in a memory usage pattern equal to a memory leak. I'd recommend b) only if the strings belong semantically to the class that provides them, similar to the std::string::c_str(). Your TextHelper looks more like a toolbox that should not be associated with the processed strings, so if I had to choose between the two, I'd go for a). Your user class is probably the best solution, given a fixed TextHelper interface.
Edit: No, I'm wrong. I misunderstood what you were trying to do. The caller must delete the memory in your instance.
The C++ standard states that deleting 0/NULL does nothing (in other words, this is safe to do), so you can delete it regardless of whether you ever called the function at all. Edit: I don't know how this got left out...your other alternative is placement delete. In that case, even if it is bad form, you should also use placement new to keep the allocation/deallocation in the same place (otherwise the inconsistency would make debugging ridiculous).
That said, how are you using the code? I don't see when you would ever call it more than once, but if you do, there are potential memory leaks (I think) if you don't remember each different block of memory.
I would just use std::auto_ptr or Boost::shared_ptr. It deletes itself on the way out and can be used with char*.
Another thing you can do, considering on how TextHelper is allocated. Here is a theoretical ctor:
TextHelper(const char* input) : input_(input), copy(0) { copy = new char[sizeof(input)/sizeof(char)]; //mess with later }
~TextHelper() { delete copy; }