I am getting the below warning at SubManager constructor:
Uninitialized scalar field (UNINIT_CTOR)
uninit_member: Non-static class member field m_cJobState.bEULA is not initialized in this constructor nor in any functions that it calls.
uninit_member: Non-static class member field m_cJobState.bstatus is not initialized in this constructor nor in any functions that it calls.
uninit_member: Non-static class member field m_cJobState.eActivationState is not initialized in this constructor nor in any functions that it calls.
Below is the code snippet:
SubManager.h file
struct MgrStatus
{
bool bEULA;
bool bstatus;
WorkState eActivationState;
};
class SubManager
{
private:
MgrStatus m_cJobState;
};
SubManager.cpp file
SubManager::SubManager()
{
}
To resolve the warning,
Do we need to initialize structure variables in the above constructor?
If we need to initialize, how to initialize the enum variable (WorkState eActivationState;)?
You did not specify from what tool you got warnings and also posted code
should give different errors I suspect. Seems that the tool requires you to initialize all aggregate members in constructors (C++ standard does not).
Since C++11 (question was tagged like that) it should compile and run with uniform initialization of aggregate members:
enum WorkState {SomethingElse, Crappy, Etc}; // wasn't defined in OP
struct MgrStatus
{
bool bEULA;
bool bstatus;
WorkState eActivationState;
};
class SubManager
{
public:
SubManager(); // constructor declaration was missing in OP
private:
MgrStatus m_cJobState;
};
SubManager::SubManager()
: m_cJobState{false,false,Crappy}
{ }
int main() // to demo it runs
{
SubManager s;
(void)s; // just to silence unused variable s warning
}
I was under the assumption that a const member must be initialized in the class constructor.
Consider following code
class ABC
{
const string a;
const string b;
const string c;
public:
ABC( struct input in): a(in.a), b(in.b){}
};
I thought this would trigger a compile time error since explicit initialization for c is missing. However this compiles and gives empty string for c under VS2012. Is this correct behavior? (or special case for string?)
const member must be initialized when declared
The above holds true for only built-in and POD types.For Non-POD types, default constructor will be called which will initialize it.
std::string is a non-POD.
As mentioned in comments by #Dan, try changing const string c; to const int c;,the compiler will complain.
I am getting no appropriate default constructor available error with the following simple piece of code:
class A
{
public:
const string cs ;
};
void main()
{
A a;
return;
}
If I remove the const from string then code compiles fine. I can not understand why the default constructor is not getting created by compiler? And what is the deal with const string member variable?
I am working on VS2008.
As mentioned in the comments, const variables cannot be left unitialized in C++. There are two ways you can initialize your variable. In both cases, the content of the string can never be modified (as this is what const means).
1) In the class declaration. This method is useful only if you always want this string to have the same value across all of your objects. It is very inflexible and if you find yourself using it you should probably declare the variable as static.
class A
{
const string cs = "value of cs";
};
2) assign it in the constructor, using constructor chaining. This is much more flexible and idiomatic.
class A
{
const string cs;
public:
A() : cs("value of cs")
{
}
};
Note that this can be used with arguments, eg
A(string s) : cs(s) //initializes cs to the value of s
Your error probably arises from the compiler trying to find the second option.
Since C++17 it is legal to have a const member with no initializer -- if that member has a default constructor which initializes itself. void main() is still incorrect though!
So here is some valid code:
#include <string>
struct A { const std::string cs; };
int main()
{
A a;
}
The string a.cs is an empty string which is const.
If using an older compiler you will have to give a redundant initializer for cs.
Is the following code safe or does it lead to undefined behavior in C++03?
class Aries {
public:
Aries() : Taurus("foo") , Leo(Taurus + "bar") {}
private:
string Taurus;
const string Leo;
};
This code is obviously a stripped down version of my actual problem.
Edit Taurus has been intentionally declared before Leo in the class declaration. I am aware the initialization happens in the order of initialization in class declaration (not the order in the initializer list.)
Just to clarify an alternative I mentioned in the comments:
class Aries {
public:
friend Aries makeAries() {
string Taurus = "foo"; // easier to do computations here:
return Aries( Taurus, Taurus + "bar" );
}
private:
Aries( string const &inTaurus, string const &inLeo )
: Taurus(inTaurus) , Leo(inLeo) {}
string Taurus;
const string Leo;
};
Aries makeAries(); // must declare a friend factory outside the class
This isn't a universal solution or a really desirable idiom, but can still be helpful and relatively clean.
Yes, you can safely use members that are initialized before the member you are initializing.
Note that the order of initialization is the order of declaration in the class definition.
I'd like to have a private static constant for a class (in this case a shape-factory).
I'd like to have something of the sort.
class A {
private:
static const string RECTANGLE = "rectangle";
}
Unfortunately I get all sorts of error from the C++ (g++) compiler, such as:
ISO C++ forbids initialization of
member ‘RECTANGLE’
invalid in-class initialization of static data member of non-integral type ‘std::string’
error: making ‘RECTANGLE’ static
This tells me that this sort of member design is not compliant with the standard. How do you have a private literal constant (or perhaps public) without having to use a #define directive (I want to avoid the uglyness of data globality!)
Any help is appreciated.
You have to define your static member outside the class definition and provide the initializer there.
First
// In a header file (if it is in a header file in your case)
class A {
private:
static const string RECTANGLE;
};
and then
// In one of the implementation files
const string A::RECTANGLE = "rectangle";
The syntax you were originally trying to use (initializer inside class definition) is only allowed with integral and enum types.
Starting from C++17 you have another option, which is quite similar to your original declaration: inline variables
// In a header file (if it is in a header file in your case)
class A {
private:
inline static const string RECTANGLE = "rectangle";
};
No additional definition is needed.
In C++11 you can do now:
class A {
private:
static constexpr const char* STRING = "some useful string constant";
};
Inside class definitions you can only declare static members. They have to be defined outside of the class. For compile-time integral constants the standard makes the exception that you can "initialize" members. It's still not a definition, though. Taking the address would not work without definition, for example.
I'd like to mention that I don't see the benefit of using std::string over const char[] for constants. std::string is nice and all but it requires dynamic initialization. So, if you write something like
const std::string foo = "hello";
at namespace scope the constructor of foo will be run right before execution of main starts and this constructor will create a copy of the constant "hello" in the heap memory. Unless you really need RECTANGLE to be a std::string you could just as well write
// class definition with incomplete static member could be in a header file
class A {
static const char RECTANGLE[];
};
// this needs to be placed in a single translation unit only
const char A::RECTANGLE[] = "rectangle";
There! No heap allocation, no copying, no dynamic initialization.
Cheers, s.
In C++ 17 you can use inline variables:
class A {
private:
static inline const std::string my_string = "some useful string constant";
};
Note that this is different from abyss.7's answer: This one defines an actual std::string object, not a const char*
This is just extra information, but if you really want the string in a header file, try something like:
class foo
{
public:
static const std::string& RECTANGLE(void)
{
static const std::string str = "rectangle";
return str;
}
};
Though I doubt that's recommended.
The class static variables can be declared in the header but must be defined in a .cpp file. This is because there can be only one instance of a static variable and the compiler can't decide in which generated object file to put it so you have to make the decision, instead.
To keep the definition of a static value with the declaration in C++11
a nested static structure can be used. In this case the static member
is a structure and has to be defined in a .cpp file, but the values
are in the header.
class A
{
private:
static struct _Shapes {
const std::string RECTANGLE {"rectangle"};
const std::string CIRCLE {"circle"};
} shape;
};
Instead of initializing individual members the whole static structure is initialized in .cpp:
A::_Shapes A::shape;
The values are accessed with
A::shape.RECTANGLE;
or -- since the members are private and are meant to be used only from A -- with
shape.RECTANGLE;
Note that this solution still suffers from the problem of the order of
initialization of the static variables. When a static value is used to
initialize another static variable, the first may not be initialized,
yet.
// file.h
class File {
public:
static struct _Extensions {
const std::string h{ ".h" };
const std::string hpp{ ".hpp" };
const std::string c{ ".c" };
const std::string cpp{ ".cpp" };
} extension;
};
// file.cpp
File::_Extensions File::extension;
// module.cpp
static std::set<std::string> headers{ File::extension.h, File::extension.hpp };
In this case the static variable headers will contain either { "" }
or { ".h", ".hpp" }, depending on the order of initialization created by the linker.
As mentioned by #abyss.7 you could also use constexpr if the value of the variable can be computed at compile time. But if you declare your strings with static constexpr const char* and your program uses std::string otherwise there will be an overhead because a new std::string object will be created every time you use such a constant:
class A {
public:
static constexpr const char* STRING = "some value";
};
void foo(const std::string& bar);
int main() {
foo(A::STRING); // a new std::string is constructed and destroyed.
}
To use that in-class initialization
syntax, the constant must be a static
const of integral or enumeration type
initialized by a constant expression.
This is the restriction. Hence, in this case you need to define variable outside the class. refer answwer from #AndreyT
possible just do:
static const std::string RECTANGLE() const {
return "rectangle";
}
or
#define RECTANGLE "rectangle"
You can either go for the const char* solution mentioned above, but then if you need string all the time, you're going to have a lot of overhead.
On the other hand, static string needs dynamic initialization, thus if you want to use its value during another global/static variable's initialization, you might hit the problem of initialization order. To avoid that, the cheapest thing is accessing the static string object through a getter, which checks if your object is initialized or not.
//in a header
class A{
static string s;
public:
static string getS();
};
//in implementation
string A::s;
namespace{
bool init_A_s(){
A::s = string("foo");
return true;
}
bool A_s_initialized = init_A_s();
}
string A::getS(){
if (!A_s_initialized)
A_s_initialized = init_A_s();
return s;
}
Remember to only use A::getS(). Because any threading can only started by main(), and A_s_initialized is initialized before main(), you don't need locks even in a multithreaded environment. A_s_initialized is 0 by default (before the dynamic initialization), so if you use getS() before s is initialized, you call the init function safely.
Btw, in the answer above: "static const std::string RECTANGLE() const" , static functions cannot be const because they cannot change the state if any object anyway (there is no this pointer).
The current standard only allows such initialization for static constant integral types. So you need to do as AndreyT explained. However, that will be available in the next standard through the new member initialization syntax.
Fast forward to 2018 and C++17.
do not use std::string, use std::string_view literals
please do notice the 'constexpr' bellow. This is also an "compile time" mechanism.
no inline does not mean repetition
no cpp files are not necessary for this
static_assert 'works' at compile time only
using namespace std::literals;
namespace STANDARD {
constexpr
inline
auto
compiletime_static_string_view_constant() {
// make and return string view literal
// will stay the same for the whole application lifetime
// will exhibit standard and expected interface
// will be usable at both
// runtime and compile time
// by value semantics implemented for you
auto when_needed_ = "compile time"sv;
return when_needed_ ;
}
};
Above is a proper and legal standard C++ citizen. It can get readily involved in any and all std:: algorithms, containers, utilities and a such. For example:
// test the resilience
auto return_by_val = []() {
auto return_by_val = []() {
auto return_by_val = []() {
auto return_by_val = []() {
return STANDARD::compiletime_static_string_view_constant();
};
return return_by_val();
};
return return_by_val();
};
return return_by_val();
};
// actually a run time
_ASSERTE(return_by_val() == "compile time");
// compile time
static_assert(
STANDARD::compiletime_static_string_view_constant()
== "compile time"
);
Enjoy the standard C++