This code crashes at the cout line. Can anyone explain why this doesn't work?
#include <iostream>
#include <string>
using namespace std;
class myclass {
const string& m_str;
public:
myclass(string s) : m_str(s) {}
const string& getString() const { return m_str; }
};
int main () {
const string str("honey");
myclass mc(str);
cout << mc.getString() << "\n";
return 0;
}
the myclass constructor is taking a string by value which makes it a temporary. You're then binding this temporary to the m_str member. As soo as the constructor exits your member reference becomes invalid. Instead: myclass(const string& s) : m_str(s) {}
Even so that may not be a good idea. Generally speaking using references as members can be dangerous because you have to be very clear about lifetime semantics. You should consider just storing the string by value in your class unless you have a specific reason not to do so.
Related
I need to initialize the const member object of a class in a constructor, but the member's constructor creates just an empty object, whereas real initialization has to be done by deserialization of this object from a file. The class of the member object is not mine and I can't change it. Namely, it's a Dlib model, the following code simulates it's behavior:
#include <iostream>
#include <string>
// not my class, can't be changed
class ShapePredictor
{
friend std::istream& operator >> (std::istream& stream, ShapePredictor&);
public:
ShapePredictor() = default;
ShapePredictor(const ShapePredictor& other) : data(other.data) { std::cout << "copy" << std::endl; }
ShapePredictor(ShapePredictor&& other) : data(std::move(other.data)) { std::cout << "moved" << std::endl; }
private:
std::string data;
};
// deserialization
std::istream& operator >> (std::istream& stream, ShapePredictor& sp)
{
sp.data = "test33";
return stream;
}
class FaceExtractor
{
public:
FaceExtractor()
{
std::cin >> this->sp; // won't compile
}
private:
const ShapePredictor sp;
};
int main(int argc, char* argv[])
{
FaceExtractor extractor;
return 0;
}
I am not sure what is the best way to do it. The first thing that springs to mind is using const_cast<>():
class FaceExtractor
{
public:
FaceExtractor()
{
std::cin >> const_cast<ShapePredictor&>(this->sp);
}
private:
const ShapePredictor sp;
};
It works, but using const_cast<>() is normally considered a bad practice. I read it is mostly designed for compatibility with legacy APIs that are not const correct. I am not quite sure whether it would be ok to use it in my case.
Another way to tackle it is to create a member function deserialize() which would load the class into a temporary object and return it:
class FaceExtractor
{
public:
FaceExtractor()
: sp(deserialize())
{ }
ShapePredictor deserialize()
{
ShapePredictor tmp;
std::cin >> tmp;
return tmp;
};
private:
const ShapePredictor sp;
};
This involves creating a temporary, which is undesirable. Hopefully, NRVO will elide a copy, but in MSVC it still costs one additional move.
I am wondering what is the common practice to initialize such kind of objects?
Just make the member variable non-const. Having const member variables is usually a pain and is rarely useful.
if you absolutely must have it const, you could make a class that inherits from ShapePredictor and add a constructor that does the streaming.
struct ShapePredictorStreamable : public ShapePredictor {
ShapePredictorStreamable(std::istream& is) {
is >> *this;
}
};
class FaceExtractor {
public:
FaceExtractor() : sp(std::cin) {}
private:
const ShapePredictorStreamable sp;
};
I have a many, MANY strings that are almost never modified after creation and access times to them is not really a concern. I have to minimize the memory usage so I opted to writing a class instead of using std::string which has to hold extra data such as capacity and length to conform with the standard. This change resulted in reduction of ~%30 memory usage.
To achieve this, I have written a class just wraps C-style null-terminated strings internally and manages the buffer so the class just consists of a pointer data member and it provides enough interface to rarely access and work with it like std::string.
I would like to avoid boilerplate code and allow transparent conversions from std::string and to std::string. So can I avoid allocating/copying the data from std::string on edge cases such as when temporary is needed? Consider this:
class A {
public:
A(const char* p) : p_{std::strdup(p)} { }
~A() { free(p_); }
A& append(const A&);
private:
char* p_;
};
Now in the following code:
A a;
a.append("test");
A temporary object will be created, allocating and copying the data. Then it will be immediately destroyed. The question is, is there a way to avoid this without creating a version of every function such as A& append(const char*). I would also like to support the transparent conversions for std::string so it will automatically become 3 versions of each function.
What effects will the following approach have:
class A {
public:
A(const char* p) : p_{std::strdup(p)} { }
A(const char* p) &&
: p_{p} {
}
~A() { free(p_); }
~A() && { /* nothing */ }
A& append(const A&);
private:
char* p_;
};
If this does not work, what strategy can I apply to solve this problem?
What effects will the following approach have:
A(const char* p) &&
~A() &&
The most likely effect is compilation error, since standard doesn't allow ref-qualifiers on c/d-tor.
I recommend implementing A::c_str just like strings do, and use the following helper from a template:
template<class Str>
const char* c_str_help(const Str& str) {
return str.c_str();
}
const char* c_str_help(const char* str) {
return str;
}
class A {
// ...
const char* c_str() const { return p_; }
template<class Str>
A& append(const Str& str) {
const char* s = c_str_help(str);
// implement using const char* s
}
};
PS: I recommend using a unique_ptr<char, void(*)(void*)> instead of a bare pointer for much easier implementation.
A bit similar to user2079303's approach, with SFINAE so we don't hinder overload resolution:
namespace detail_A {
char const *getString(std::string const &str) {
return str.c_str();
}
char const *getString(char const *str) {
return str;
}
// More `getString`s as needed...
template <class T>
using enableString = decltype(getString(std::declval<T>()));
}
class A {
// ...
template <class T, class = detail_A::enableString<T>>
A &append(T const &str) {
char const *p = detail_A::getString(str);
std::cout << "Appending \"" << p << "\"\n";
return *this;
}
};
See it live on Coliru
Current get() member function in class MyClass is defined as below, the return type is const int&. My question is what would be the difference if I defined get() function as
int& get() const
or
int get() const
? And which way is recommended?
#include <iostream>
using namespace std;
class MyClass {
int x;
public:
MyClass(int val) : x(val) {}
const int& get() const {return x;}
};
void print (const MyClass& arg) {
cout << arg.get() << '\n';
}
int main() {
MyClass foo (10);
print(foo);
return 0;
}
There's really nothing wrong with this code; logically it accomplishes more or less the same thing after the compiler inlines the get() method.
There's quite a big difference in some degenerate callers though:
const int *iptr = &foo.get(); // returns the address of x in the class.
On the other hand had you declared as follows:
class MyClass {
int x;
public:
MyClass(int val) : x(val) {}
const int get() const {return x;}
};
const int *iptr = &foo.get(); // Error!
I don't see any good reason for int& here. If you don't have one, people will frown on this code. Normally if people are expected to keep pointers to things around you don't return them by reference. The only reason you would want to return a pointer to a member is so that somebody can auto-pickup changes to it; and I have never seen a good use for that though I can imagine why some such thing might exist.
As for selbie's comment about assigning to it; it's a const reference; assigning to it is a compile time error.
I am trying to create a Person class in which I have decided to keep the name and gender constant. Here is the class definition:
class Person
{
const char *name;
int age;
const char *gen;
protected:
Person(const char *, const int ,const char *); // I want to use this class as a Base class
public:
~Person();
}
Now my problem is how to initialize the constant data members. I know that I have to use initialization lists for this task but even then how do I allocate memory for the char pointers with new? Also I cannot initialize these pointers in the constructor body. Please help me find a solution.
You can use the initializer list as following, you don't need to allocate the char array in this construction. I have simplified the class, as your question is about the const char*.
#include <iostream>
#include <string>
class Person
{
public:
Person(const char* name, const std::string better_name) :
name(name), better_name(better_name) {}
void print_name()
{
std::cout << name << " and " << better_name << std::endl;
}
private:
const char* name;
const std::string better_name;
};
int main()
{
Person person("Billy", "Better Billy");
person.print_name();
return 0;
}
Let me preference that I mostly develop in C# and the C++ development which I have done did not fully leverage the C++ language. I am now trying to use the language as it was intended and I am pulling my hair out with const declarations in passed arguments. In the past I never used them or hacked my way into making them work with the STL.
My understanding that I would create the following function when I want to use o as readonly in the function:
void foo(const MyClass* o);
So here is my problem...code first:
#include <iostream>
#include <string>
using namespace std;
///////////////////////////////////////////////////////////
// Classes are defined in the one file for an easy post.
///////////////////////////////////////////////////////////
class ClassA {
private: // member variables
string m_name;
public: // constructors
ClassA(const string& name = "") : m_name{name} {}
virtual ~ClassA() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
};
class ClassB {
private: // member variables
string m_name;
ClassA m_child;
public: // constructors
ClassB(const string& name = "") : m_name{name} {}
virtual ~ClassB() { }
public: // accessors
const string& name() const { return m_name; }
void setName(const string& value) { m_name = value; }
ClassA* child() { return &m_child; }
void setChild(const ClassA* value) { m_child = *value; }
};
///////////////////////////////////////////////////////////
// Protoptypes are not used to save space for the post.
void doSomethingA(const ClassA* o) {
cout << "name = " << o->name() << endl << endl;
}
void doSomethingB(const ClassB* o) {
cout << "name = " << o->name() << endl << endl;
doSomethingA(o->child());
}
///////////////////////////////////////////////////////////
int main(int argc, char** argv) {
ClassA a { "My Class A" };
ClassB b { "My Class B" };
b.setChild(&a);
b.child()->setName("My New Name");
doSomethingB(&b);
return 0;
}
In main() the compiler (g++ version 4.7.2) balks in doSomethingB:
doSomethingA(o->child());
with error: passing 'const ClassB' as 'this' argument of 'ClassA* ClassB::child()' discards qualifiers [-fpermissive]
Now I am passing my classes to functions as pointers. I plan on always using pointers because I have a problem with the reference/pointer options. I'm choosing one, pointers, and sticking with it. So doSomethingA and doSomethingB I want that to be const to tell the programmer that their class is not being altered. But I only want one version of child() which I want to use sometimes as "read only" and other times allow the user to change the data within the child object (not the best method, I grant that, but there are some use cases where I need this). I even tried:
doSomethingA(const_cast<const ClassA*>(o->child()));
But that did not work.
In the past I removed the const declarations in the functions to make something like this work but now I want to use proper c++. Help please.
try
ClassA* child() const { return &m_child; }
or
const ClassA* child() const { return &m_child; }
to keep the const correctness
Also, you don't need to use pointers as long as you don't plan passing nullptr. So you can do the following:
void doSomethingB(const ClassB& o);
// in class ClassB
const ClassA& child() const { return m_child; }
ClassA& child() { return m_child; }
References still alow polymorphic stuff same way as pointers.
You're attempting to access a non-const function against a const object. You need to make the function const :
const ClassA* child() const { return &m_child; }
You can also provide a const and non-const version:
ClassA* child() { return &m_child; }
const ClassA* child() const { return &m_child; }
This way you can call non-const methods on ClassA when you have a non-const object.