Correct way of declaring a static string variable? [duplicate] - c++

Clang warns (when using -Weverything or Wglobal-constructors) about constructors for static objects.
warning: declaration requires a global constructor
[-Wglobal-constructors]
A A::my_A; // triggers said warning
^~~~
Why is this relevant and how should one deal with this warning?
Simple example code:
class A {
// ...
static A my_A;
A();
};
A A::my_A; // triggers said warning

Here is a simpler case that triggers the same warning:
class A {
public:
// ...
A();
};
A my_A; // triggers said warning
test.cpp:7:3: warning: declaration requires a global constructor [-Wglobal-constructors]
A my_A; // triggers said warning
^~~~
1 warning generated.
This is perfectly legal and safe C++.
However for every non-trivial global constructor you have, launch time of your application suffers. The warning is simply a way of letting you know about this potential performance problem.
You can disable the warning with -Wno-global-constructors. Or you can change to a lazy initialization scheme like this:
A&
my_A()
{
static A a;
return a;
}
which avoids the issue entirely (and suppresses the warning).

Solution from #Howard Hinnant avoid global constructor, but it do exit time destructor still.
It can be found with option -Wexit-time-destructors
So Ideal solution can be based on CR_DEFINE_STATIC_LOCAL from http://src.chromium.org/svn/trunk/src/base/basictypes.h
A& my_A()
{
static A &a = *new A;
return a;
}

If you can declare the constructor constexpr, that will suppress the warning (because this guarantees constant initialization). See https://godbolt.org/z/s3hY83jdr

Related

Clang warning on global destructor [duplicate]

Clang warns (when using -Weverything or Wglobal-constructors) about constructors for static objects.
warning: declaration requires a global constructor
[-Wglobal-constructors]
A A::my_A; // triggers said warning
^~~~
Why is this relevant and how should one deal with this warning?
Simple example code:
class A {
// ...
static A my_A;
A();
};
A A::my_A; // triggers said warning
Here is a simpler case that triggers the same warning:
class A {
public:
// ...
A();
};
A my_A; // triggers said warning
test.cpp:7:3: warning: declaration requires a global constructor [-Wglobal-constructors]
A my_A; // triggers said warning
^~~~
1 warning generated.
This is perfectly legal and safe C++.
However for every non-trivial global constructor you have, launch time of your application suffers. The warning is simply a way of letting you know about this potential performance problem.
You can disable the warning with -Wno-global-constructors. Or you can change to a lazy initialization scheme like this:
A&
my_A()
{
static A a;
return a;
}
which avoids the issue entirely (and suppresses the warning).
Solution from #Howard Hinnant avoid global constructor, but it do exit time destructor still.
It can be found with option -Wexit-time-destructors
So Ideal solution can be based on CR_DEFINE_STATIC_LOCAL from http://src.chromium.org/svn/trunk/src/base/basictypes.h
A& my_A()
{
static A &a = *new A;
return a;
}
If you can declare the constructor constexpr, that will suppress the warning (because this guarantees constant initialization). See https://godbolt.org/z/s3hY83jdr

c++17: inner class default member initializer ignored in static inline varilables [duplicate]

struct sa
{
struct sb { int a = 123;};
inline static sb b;
};
The above code generates an error:
main.cpp:25:20: error: default member initializer for ‘sa::sb::a’ required before the end of its enclosing class
inline static sb b;
^
main.cpp:24:21: note: defined here
struct sb { int a = 123;};
^~~~~~
Removing the inline keyword or the default member initializer works. But just from the output, I don't understand why this usage is wrong.
I think this code is correct and should be accepted; gcc and clang are erring on the side of caution in order to avoid the defect of Core Issue 1397.
That issue ruled that a program is ill-formed if a NSDMI (non-static data member initializer) causes the class's defaulted default constructor to be generated.
However your code doesn't do that. The NSDMI is just an integer literal. The example that prompted this issue had code like int a = ( (sa(), 123) );
What I guess might be happening is: The standard also says that , when processing the NSDMI, the class sa should be treated as complete. So perhaps the compilers are deferring the NSDMI processing until after the closing brace of sa is reached; and then flagging the error because inline static sb b; would generate sb::sb().
Possibly the standard is still defective and nobody thought of your example until now.
As a workaround you can explicitly provide the troublesome constructor:
struct sb { int a = 123; sb() {} };

Is it bad practice to initialize variables in class members?

If a variable's intended scope is truly local, it would only make sense to me to keep it that way. This is what I have always done. However I recently switched from vim to eclipse at work and eclipse is flagging my constructor if every member variable is not initialized in the constructor. For example, in the code below, it compiles just fine. g++ has no problem with it. Eclipse on the other hand tells me that 'a' should be initialized in the constructor.
Is there any reason why this warning might be relevant or is it just worth ignoring all together?
class C
{
public:
C(){}
~C(){}
void foo();
};
void C::foo()
{
int a;
}
int main() {
C c;
return 0;
}
Eclipse on the other hand tells me that 'a' should be initialized in the constructor.
a cannot be initialized in the constructor because it's a local variable of the member function C::foo(). Eclipse is giving you a bogus warning.

Is there a way to force the "most vexing parse" to be an error, even on a class by class basis?

Is it possible (with any modification of class A) to have the following work? i.e., make the most vexing parse an error?
class A {
};
int main() {
A a(); // can this be forced to be an error??
A b; // this should work
}
No modification of the class A will have any effect on how a declaration A a(); is parsed. The parser determines that this is a function declaration before it even bothers to look at the definition of A. In fact the definition of A doesn't even need to be visible to parse this statement; A forward declaration is sufficient.
However compilers generally have a warning for this and you can probably turn that into an error. For example with clang you can use the flag -Werror=vexing-parse.
struct A;
A a(); // no error
int main() {
A a(); // error
}
clang++ -std=c++11 -Weverything -Werror=vexing-parse main.cpp
main.cpp:6:8: error: empty parentheses interpreted as a function declaration [-Werror,-Wvexing-parse]
A a();
^~
main.cpp:6:8: note: replace parentheses with an initializer to declare a variable
A a();
^~
{}
1 error generated.
Although technically speaking A a(); isn't the syntax known as the most vexing parse. That would be:
A a(B());
There is no way in the current language specification which could make this code an error. Normally, you just get a funny error message when you try to use the "object". However, some compilers do warn about the situation (e.g. clang):
clang++ -W -Wall -Werror -c -o vexing.o vexing.cpp
vexing.cpp:5:8: error: empty parentheses interpreted as a function declaration [-Werror,-Wvexing-parse]
A a(); // can this be forced to be an error??
^~

How to deal with global-constructor warning in clang?

Clang warns (when using -Weverything or Wglobal-constructors) about constructors for static objects.
warning: declaration requires a global constructor
[-Wglobal-constructors]
A A::my_A; // triggers said warning
^~~~
Why is this relevant and how should one deal with this warning?
Simple example code:
class A {
// ...
static A my_A;
A();
};
A A::my_A; // triggers said warning
Here is a simpler case that triggers the same warning:
class A {
public:
// ...
A();
};
A my_A; // triggers said warning
test.cpp:7:3: warning: declaration requires a global constructor [-Wglobal-constructors]
A my_A; // triggers said warning
^~~~
1 warning generated.
This is perfectly legal and safe C++.
However for every non-trivial global constructor you have, launch time of your application suffers. The warning is simply a way of letting you know about this potential performance problem.
You can disable the warning with -Wno-global-constructors. Or you can change to a lazy initialization scheme like this:
A&
my_A()
{
static A a;
return a;
}
which avoids the issue entirely (and suppresses the warning).
Solution from #Howard Hinnant avoid global constructor, but it do exit time destructor still.
It can be found with option -Wexit-time-destructors
So Ideal solution can be based on CR_DEFINE_STATIC_LOCAL from http://src.chromium.org/svn/trunk/src/base/basictypes.h
A& my_A()
{
static A &a = *new A;
return a;
}
If you can declare the constructor constexpr, that will suppress the warning (because this guarantees constant initialization). See https://godbolt.org/z/s3hY83jdr