Passing a string as a const char* - c++

I have access to a class (not written by me) that takes a const char* as a parameter in the constructor. If I have a string that I want to pass the value of as a parameter, what is the safe way to pass it, keeping in mind that the string and the class object may have different scopes?
I don't have access to the source code for the class, so don't assume it's doing something sane like copying the string into a class member.
As a concrete example, this doesn't work:
#include <iostream>
#include <string>
class example {
public:
example(const char*);
const char* str;
};
example::example(const char* a) : str(a) {}
int main() {
std::string* a=new std::string("a");
example thisDoesntWork(a->c_str());
std::cout << thisDoesntWork.str << std::endl;
delete a;
std::cout << thisDoesntWork.str << std::endl; //The pointer is now invalid
a=new std::string("b");
std::cout << thisDoesntWork.str << std::endl;
}
Replacing the constructor with this works (so far as I can tell) but is clearly pretty awful:
example thisDoesWorkButIsAwful((new const std::string(*a))->c_str()); //Memory leak!
Similarly:
char* buffer=new char[a->size()+1];
strcpy(buffer,a->c_str()); //with #include <string.h> added up top
example(buffer);
But again, this is prone to memory leaks.
My main idea at the moment is to make a wrapper class around example that copies the string into a char * buffer and deletes the buffer when it goes out of scope, but that seems a little heavy-handed. Is there an easier/better way?

Fundamentally, something needs to hold on to the memory - either you do it yourself or have it done automatically.
One way to do it automatically:
class SuperThatHoldsIt
{
std::string mString ;
SuperThatHoldsIt ( std::string const& str )
: mString ( str ) { }
} ;
class HoldingExample
: private SuperThatHoldsIt
, public example
{
holdingExample ( std::string const& string )
: SuperThatHoldsIt ( string )
, example ( mString.c_str() )
{ }
} ;
Then create it in a std::shared_ptr (or boost::shared_ptr) which will hold on to it.
std::string myString ( "Hello, world!" ) ;
std::shared_ptr<HoldingExample> value = std::make_shared<HoldingExample> ( myString ) ;
Now this holds onto the memory AND the structure.
Notes:
The reason HoldingExample derives from two supers is to that the order of constructors will work out because superclasses are always initialized before local variables. This means we have to construct example before our own member variables, but we can always initialize a superclass's and use its member variables.
If you pass this into a function, like
callFunction ( *value ) ;
If they hold on to that const char* after you've let go of your value, then you'll still have a leak and you really can't get around that.

Related

When should I use std::string / std::string_view for parameter / return type

Introduction
I'm writing some communication application. Before C++17 (without Boost), I use std::string and its const reference as cls1.
Since C++17, I introduced std::string_view to my code as cls2.
However, I don't have clear policy when should I use std::string_view. My communication application receives data from the network and it is stored to recv_buffer. And creates some application classes from recv_buffer.
Construction
If I focus only cls1's constructor, move construction is efficient. But I think that where the parameter s from. If it is originally from the recv_buffer, I can create std::string_view at the receiving (very early) point. And during recv_buffer's lifetime is enabled, use std::string_view everywhere. If I need to store the part of recv_buffer then create std::string.
An only exception I noticed is the recv_buffer is always contained complete data for my application class. In this case, move construction is efficient.
Getter
I think using the return type as std::string_view has advantage. Some member function such as substr() is efficient. But I don't see any disadvantage, so far.
Question
I suspect that I might see only pros of std::string_view. Before re-writing many codes, I would like to know your ideas.
PoC code
#include <string>
struct cls1 {
explicit cls1(std::string s):s_(std::move(s)) {}
std::string const& get() const { return s_; }
private:
std::string s_;
};
struct cls2 {
explicit cls2(std::string_view s):s_(s) {}
std::string_view get() const { return s_; }
private:
std::string s_;
};
#include <iostream>
int main() {
// If all of the receive buffer is the target
{
std::string recv_buffer = "ABC";
cls1 c1(std::move(recv_buffer)); // move construct
std::cout << c1.get().substr(1, 2) << std::endl; // create new string
}
{
std::string recv_buffer = "ABC";
cls2 c2(recv_buffer); // copy happend
std::cout << c2.get().substr(1, 2) << std::endl; // doesn't create new string
}
// If a part of the receive buffer is the target
{
std::string recv_buffer = "<<<ABC>>>";
cls1 c1(recv_buffer.substr(3, 3)); // copy happend and move construct
std::cout << c1.get().substr(1, 2) << std::endl; // create new string
}
{
std::string recv_buffer = "<<<ABC>>>";
std::string_view ref = recv_buffer;
cls2 c2(ref.substr(3, 3)); // string create from the part of buffer directly
std::cout << c2.get().substr(1, 2) << std::endl; // doesn't create new string
}
}
Running Demo: https://wandbox.org/permlink/TW8w3je3q3D46cjk
std::string_view is a way to get some std::string const member functions without creating a std::string if you have some char* or you want to reference subset of a string.
Consider it as a const reference. If the object it refers vanishes (or changes) for any reason, you have a problem. If your code can return a reference, you can return a string_view.
Example:
#include <cstdio>
#include <string>
#include <vector>
#include <string.h>
#include <iostream>
int main()
{
char* a = new char[10];
strcpy(a,"Hello");
std::string_view s(a);
std::cout << s; // OK
delete[] a;
std::cout << s; // whops. UD. If it was std::string, no problem, it would have been a copy
}
More info.
Edit: It doesn't have a c_str() member because this needs the creation of a \0 at the end of the substring which cannot be done without modification.
Don't return a string view when:
The caller needs a null terminated string. This is often the case when dealing with C API's.
You don't store the string itself somewhere. You do store the string in a member in this case.
Do realise, that the string view becomes invalidated by operations on the original string such as changing the capacity, as well as if the original string is destroyed. If the caller needs the string for a longer than the life time of the object that stores the string, then they can copy from the view into their own storage.

How can I access an array stored in an object?

I'm quite new to C++. I've been trying to figure this out for days - there'll be an easy solution no doubt but I haven't been able to find it (after much googling)! My problem is this:
I'm trying to create a class with a member function that reads in characters from a file and stores them in an array. I want to be able to create multiple objects (not sure how many - decided by the user), each with their own arrays filled with characters taken from different files. I think I've managed to do that. How would I then go about accessing the object's array in main?
The code I'm working on is long and messy but something along these lines (char.txt contains simply '12345' in this case):
#include <iostream>
#include <fstream>
using namespace std;
class Something{
public:
void fill_array(char array_to_fill[]){
char next;
ifstream input;
input.open("chars.txt");
input.get(next);
while(!input.eof())
{
for(int i = 0; i < 6; i++)
{
array_to_fill[i] = next;
input.get(next);
}
}
}
};
int main()
{
Something* something = new Something[1];
char array_to_fill[5];
something->fill_array(array_to_fill);
//I'd like to be able to access the array here; for example - to cout the array.
return 0;
}
Apologies if a) my terminology is wrong b) my code is rubbish or c) my question is stupid/doesn't make sense. Also I should add I haven't learnt vectors yet and I'm not supposed to use them for the program I'm making. Any help would be much appreciated. Cheers!
Your class does not store the array at all. It is simply a holder for a method. You probably want something like this, where each instance of the class holds the array. (I changed it to std::string since they are nicer to work with.)
class Something
{
private:
std::string data;
public:
void fill_data( const std::string& filename )
{
ifstream file( filename );
file >> data;
file.close();
}
std::string get_data() const
{
return data;
}
}
int main()
{
std::vector<Something> my_things;
my_things.push_back( Something() );
my_things[0].fill_data( "chars.txt" );
cout << my_things[0].get_data() << std::endl;
my_things.push_back( Something() );
my_things[1].fill_data( "another_file.txt" );
cout << my_things[1].get_data() << std::endl;
}
Since you are using C++, not C, get used to writing C++ code instead of C. (std::vector instead of C arrays (for unknown length arrays), std::string instead of char*, etc).
I think your question is too general for the format of stack overflow, but what you want in this case is to either create a public member, or create a private member with setters and getters.
class Something
{
public:
std::string m_string;
}
int main()
{
Something A;
A.m_string = "toto";
cout << A.m_string;
return 0;
}
Put a string for convenience (you could use a const char* but you will have to understand what is the scope to know when it will not be accessible anymore and you are not quite there yet) and there may be typos since I typed this from a phone.
If you really want to access the chars themselves, pass a char* with a size_t for the length of the array or use std::array if possible.
Right now the method fill_array is creating a local copy of array_to_fill, so any changes that you make to array_to_fill only happen in the local method. To change this, pass by pointer. This way the pointer gets copied instead of the whole array object. I didn't test this but it should look more like this:
void fill_array(char* array_to_fill){
...
}
You don't need to change anything in the main method.
To actually access the elements you can use [] notation. I.e. cout << array_to_fill[0] in the main method.
Edit: I think that change should work.

stl map<char*,char*> destructor

I know that a map destructor calls each of the contained element's destructors. What happens for a
map<char*,char*> ?
I cannot see where this code is in /usr/include/c++/4.4
EDIT:
I should have said
map<const char*, const char*, ltstr>
like in
http://www.sgi.com/tech/stl/Map.html
When a map<char*,char*> is destroyed, so are all of the elements it contains. Each element's destructor is called, if it is of class type.
However, keep in mind exactly what is contained in your map above. It isn't strings, as you might expect -- it's just pointers to strings. The strings themselves aren't destroyed. Only the pointers are. delete is never called on the pointers.
Case in point:
map<char*, char*> strings;
char* key = new char[10];
char* value = new char[256];
/* ... */
strings.insert(key,value);
In the above, since delete is never called on the pointers created by the calls to new, this memory will leak when strings goes out of scope.
This is a good illustration of why you should avoid using raw pointers, new and delete. In your case, map<string,string> would probably be a better choice.
EDIT:
As #sbi mentioned in the comments, another reason why you would want map<string,string> over map<char*,char*> is because with map<string,string> keys are compared by-value, rather than by-pointer-value.
Consider:
#include <map>
#include <iostream>
#include <string>
using namespace std;
int main()
{
static const char MyKey[] = "foo";
const char bar[] = "bar";
typedef map<const char*,const char*> Strings;
Strings strings;
strings.insert(make_pair(MyKey,bar));
string ss = "foo";
Strings::const_iterator it = strings.find(ss.c_str());
if( it == strings.end() )
cout << "Not Found!";
else
cout << "Found";
}
Fundamentally, you're inserting an element with the key "foo" and then searching for that element. Test the above code, and you'll find that it isn't found. If, however, you try this:
#include <map>
#include <iostream>
#include <string>
using namespace std;
int main()
{
typedef map<string,string> Strings;
Strings strings;
strings.insert(make_pair("foo","bar"));
string ss = "foo";
Strings::iterator it = strings.find(ss);
if( it == strings.end() )
cout << "Not Found~!";
else
cout << "Found";
}
...you get the behavior you really wanted.
What happens
Nothing. If you dynamically allocated memory, it'll leak - there's no automatic destructor for char*.
Use std::string or similar class instead.
I do agree that std::map<string, string> will have advantages over std::map<char*, char*>. Specially having the key as value rather than pointer would provide the expected search/find results.
But, sometimes we do need pointer in map definition specially in the value part when map’s value part is heavy object of a user defined class. By heavy object , I mean copy constructor of the class does a significant amount of work. In such scenarios, value part of the map should be a pointer. Using a raw pointer would leak the memory as mentioned above. Smart pointer would be a better choice ensuring no memory is leaked.
Sample example:
Consider the below class
class ABCD
{
public:
ABCD(const int ab) : a(ab)
{cout << "Constructing ABC object with value : " << a << endl;}
~ABCD()
{cout << "Destructing ABC object with value : "<< a << endl;}
void Print()
{ cout << "Value is : " << a << endl;}
private:
int a;
};
Consider the code where-in smart pointer of the above class is used:
{
std::map<_tstring, std::shared_ptr<ABCD>> myMap;
_tstring key(_T("Key1"));
myMap.insert(std::make_pair(key, std::make_shared<ABCD>(10)));
auto itr = myMap.find(key);
itr->second->Print();
myMap[key] = std::make_shared<ABCD>(20);
itr = myMap.find(key);
itr->second->Print();
} // myMap object is destroyed, which also calls the destructor of ABCD class
Output from above code is:
Constructing ABC object with value : 10
Value is : 10
Constructing ABC object with value : 20
Destructing ABC object with value : 10
Value is : 20
Destructing ABC object with value : 20

std::cout of string not working

I have a class State that has a string data type called moveType. In the implementation of my code, I am calling a setter void setMoveType(string _moveType); and it's implemented with just moveType = _moveType;
When I call my getter string getMoveType() const; on an instance of State and output it to cout, nothing is displayed.
I am couting upon entering the getMoveType() function. The parameter indeed has the correct value, but it appears that it's not getting set at all.
Does anyone have any idea? I feel this is something simple/trivial in c++ that I'm just completely forgetting.
string State::getMoveType() const {
return moveType;
}
void State::setMoveType(string move_type) {
cout << "In setMoveType and param = " << move_type << endl;
moveType = move_type;
}
std::cout << vec_possibleSuccessors[i].getMoveType() << endl; // within loop;
vector<State> vec_possibleSuccessors;
if (_minState.canMoveUp()) {
up = _minState.moveUp();
up.setMoveType("UP");
up.setF(f(up));
vec_possibleSuccessors.push_back(up);
}
In the above code, _minState and up are instances of State. Also, I have made sure that my copy constructor and assignment operator have been modified to include moveType assignments.
There isn't really enough code to know for sure, but I have a guess: Either you actually assigned to a shadowed variable in the "set" function and never set the class attribute at all, or your State object has actually been destroyed and the string becomes empty (since being empty is one possible option when using destroyed memory).
Well not an answer but a short example that works the way you seem to intend this to work:
#include <string>
class State
{
private:
std::string m_moveType;
public:
State() : m_moveType( "unknown" ) {}
std::string getMoveType() const { return m_moveType; }
void setMoveType( const std::string& moveType ) { m_moveType = moveType; }
};
In your main function or were else you need a vector of States you could write this:
#include <iostream>
#include <vector>
#include "State.h"
int main()
{
std::vector< State > states;
for( int i=0; i<10; ++i )
{
State newState;
newState.setMoveType( "state" );
states.push_back( newState );
}
// do whatever you need to do....
std::vector< State >::iterator it;
std::vector< State >::iterator end = states.end();
for( it=states.begin(); it != end; ++it )
std::cout << (*it).getMoveType() << std::endl;
return 0;
}
A few remarks:
passing parameters by value like setMoveType( string s ) is not
adviseable, pass const references instead. Passing by value incurrs a
full copy of the passed object
be careful with includes and namespaces, in doubt take the extra time
to type std::... if you intend to use a feature defined in namespace
std, and never type using namespace std in a header file.
initialize private members to a sensible default and do it in the class
initializer list
I'm not sure on this either, but you appear to be storing this State in a vector. Could you post the code to how you set elements in the vector? Its important to note that you can't update an element in a vector once its inserted (unless you store a pointer to the element). Also depending upon how you call set, there may be problems.

Overallocating with new/delete

Using malloc and free, it is easy to allocate structures with extra data beyond the end. But how do I accomplish the same with new/ delete?
I know I could use placement new syntax along with malloc for the allocation part, but will delete work properly and portably if I place an object in memory allocated by malloc?
What I want to accomplish is the same as the following example, but using new/ delete instead of malloc/ free, so that constructors/destructors will be called properly:
#include <cstdlib>
#include <cstring>
#include <iostream>
class Hamburger {
int tastyness;
public:
char *GetMeat();
};
char *Hamburger::GetMeat() {
return reinterpret_cast<char *>(this) + sizeof(Hamburger);
}
int main(int argc, char* argv[])
{
Hamburger* hb;
// Allocate a Hamburger with 4 extra bytes to store a string.
hb = reinterpret_cast<Hamburger*>(malloc(sizeof(Hamburger) + 4));
strcpy(hb->GetMeat(), "yum");
std::cout << "hamburger is " << hb->GetMeat() << std::endl;
free(hb);
}
Output: hamburger is yum
You can do this without resorting to malloc/free or undefined behavior (I'm not sure about the reinterpret_cast, but at least construction/destruction can be done just fine).
To allocate the memory you can just call the global operator new directly. After that you use good old placement new to construct the object there. You have to guard the ctor-call though, since the "placement delete" function that's called if the ctor fails will not release any memory but just do nothing (just as placement new does nothing).
To destroy the object afterwards you can (and may) call the destructor directly, and to release the memory you can call the global operator delete.
I think it should also be OK to just delete it as you would any normal object, since calling the destructor and global operator delete afterwards is just what the normal delete will do, but I'm not 100% sure.
Your example modified like that:
#include <cstdlib>
#include <cstring>
#include <iostream>
class Hamburger {
int tastyness;
public:
char *GetMeat();
};
char *Hamburger::GetMeat() {
return reinterpret_cast<char *>(this) + sizeof(Hamburger);
}
int main(int argc, char* argv[])
{
Hamburger* hb;
// Allocate space for a Hamburger with 4 extra bytes to store a string.
void* space = operator new(sizeof(Hamburger) + 4);
// Construct the burger in that space
hb = new (space) Hamburger; // TODO: guard ctor call (release memory if ctor fails)
strcpy(hb->GetMeat(), "yum"); // OK to call member function on burger now
std::cout << "hamburger is " << hb->GetMeat() << std::endl;
// To delete we have to do 2 things
// 1) call the destructor
hb->~Hamburger();
// 2) deallocate the space
operator delete(hb);
}
If I were you, I'd use placement new and an explicit destructor call instead of delete.
template< typename D, typename T >
D *get_aux_storage( T *x ) {
return reinterpret_cast< D * >( x + 1 );
}
int main() {
char const *hamburger_identity = "yum";
void *hamburger_room = malloc( sizeof( Hamburger )
+ strlen( hamburger_identity ) + 1 );
Hamburger *hamburger = new( hamburger_room ) Hamburger;
strcpy( get_aux_storage< char >( hamburger ), hamburger_identity );
cout << get_aux_storage< char const >( hamburger ) << '\n';
hamburger->~Hamburger(); // explicit destructor call
free( hamburger_room );
}
Of course, this kind of optimization should only be done after profiling has proven the need. (Will you really save memory this way? Will this make debugging harder?)
There might not be a significant technical difference, but to me new and delete signal that an object is being created and destroyed, even if the object is just a character. When you allocate an array of characters as a generic "block," it uses the array allocator (specially suited to arrays) and notionally constructs characters in it. Then you must use placement new to construct a new object on top of those characters, which is essentially object aliasing or double construction, followed by double destruction when you want to delete everything.
It's better to sidestep the C++ object model with malloc/free than to twist it to avoid dealing with data as objects.
Oh, an alternative is to use a custom operator new, but it can be a can of worms so I do not recommend it.
struct Hamburger {
int tastyness;
public:
char *GetMeat();
static void *operator new( size_t size_of_bread, size_t size_of_meat )
{ return malloc( size_of_bread + size_of_meat ); }
static void operator delete( void *ptr )
{ free( ptr ); }
};
int main() {
char const *hamburger_identity = "yum";
size_t meat_size = strlen( hamburger_identity ) + 1;
Hamburger *hamburger = new( meat_size ) Hamburger;
strcpy( hamburger->GetMeat(), hamburger_identity );
cout << hamburger->GetMeat() << '\n';
}
Urgh. Well, let's see. You definitely can't allocate with new/malloc and dispose with free/delete. You have to use matching pairs.
I suppose you could use "hp = new char[sizeof(Hamburger) + 4]" and "delete[]((char *) hp)", along with explicit constructor/destructor calls, if you really wanted to do this.
The only reason I can think why you'd want to do this would be you didn't have the Hamburger source -- i.e., it was a library class. Otherwise you'd just add a member to it! Can you explain why you'd want to use this idea?
There is another way that you could approach this if you have a reasonably constrained set of padding amounts. You could make a template class with the padding amount as the template parameter and then instantiate it with the set of possible padding amounts. So if, for example, you knew that you were only going to need padding of 16, 32, or 64 bytes, you could do it like this:
template <int Pad>
class Hamburger {
int tastiness;
char padding[Pad];
};
template class Hamburger<16>;
template class Hamburger<32>;
template class Hamburger<64>;
Is there any reason why the straightforward, easy and safe way is not applicable?
class Hamburger {
public:
void Extend( const std::string& pExtension) {
mContent += pExtension;
}
const std::string& GetMeat() ...
private:
std::string mContent;
};
int main() {
Hamburger hb;
hb.Extend("yum");
std::cout << "hamburger is " << hb.GetMeat() << std::endl;
}