C++ vector as class member vs in function - c++

When I am using vector as following in a function, I get a variable D and it works.
vector<int> D(100);
However, when I decide to use this as a class member, I get the following weird error :
error: expected identifier before numeric constant
99 | vector<int> D(100);
| ^~~
Could someone explain why this particular error ?
I can use array in a class as int D[100].

Default member initializer (since C++11) for member variable only supports equal-sign initializer (and braced-initializer, which doesn't match this use-case).
Through a default member initializer, which is a brace or equals initializer included in the member declaration and is used if the member is omitted from the member initializer list of a constructor.
You can
vector<int> D = vector<int>(100);
Or use member intializer list. e.g.
struct x {
vector<int> D;
x() : D(100) {}
};

Related

Constructor implicitly deleted

The related code is listed below, you could check it on https://godbolt.org/z/3GH8zD.
I could solve the complier compile error indeed.But i am not completely clear about the reason lie behind it.I would be grateful to have some help with this question.
struct A
{
int x;
A(int x = 1): x(x) {} // user-defined default constructor
};
struct F : public A
{
int& ref; // reference member
const int c; // const member
// F::F() is implicitly defined as deleted
};
int main()
{
F f; // compile error
}
Compiler compliains:
Could not execute the program
Compiler returned: 1
Compiler stderr
<source>:10:15: error: declaration does not declare anything [-fpermissive]
10 | const int; // const member
| ^~~
<source>: In function 'int main()':
<source>:16:9: error: use of deleted function 'F::F()'
16 | F f; // compile error
| ^
<source>:7:12: note: 'F::F()' is implicitly deleted because the default definition would be ill-formed:
7 | struct F : public A
| ^
<source>:7:12: error: uninitialized reference member in 'struct F'
<source>:9:14: note: 'int& F::ref' should be initialized
9 | int& ref; // reference member
| ^~~
The right code may be:
struct F
{
int& ref = x; // reference member
const int c = 1; // const member
// F::F() is implicitly defined as deleted
};
The class member int& ref needs to be bound to an int when an object of type F is created.
A compiler-generated default constructor would not know how to bind it, so the compiler merely deletes the default constructor.
In the second snippet you explicitly set the member. (You can do that from C++11).
Have a look at the Deleted implicitly-declared default constructor section in cppreference. It explains under which circumstances the default constructor is deleted:
T has a member of reference type without a default initializer. (since C++11)
T has a const member without user-defined default constructor or a default member initializer (since C++11).
That is, if you don't default initialize your const and reference member variables, the constructor will be deleted and it also explains why your second attempt "worked". In fact, it doesn't work until you make F inherit from A (I guess this was your intention). Otherwise, you can't assign A::x to F::ref.
Note: Even though F::ref=A::x is allowed, there is no point in doing that since F already has access to A::x due to inheritance.
To try to build on #Bathsheba answer.
Let's first understand what a reference is. A reference is essentially a pointer that can't be null this makes them very tricky to initialize.
Let's look at your second class:
struct F : public A
{
int& ref; // reference member
const int c; // const member
// F::F() is implicitly defined as deleted
};
If instead of defining it as int& ref; we define it as int ref; the compiler will say, I have no idea what ref is supoosed to be, so I'll stick some random value into it and be done. And so the default constructor just does ref = /*some num*/;
Let's say it was a pointer instead, i.e int* ref; Once again, the default constructor needs to initialize it to a value, for pointers the most logical value for default initialization is nullptr and so we get int* ref = nullptr;
But what if it is a reference? i.e int& ref;. We can;t initialize the variable to a number, because it is not a number it's a reference "i.e a pointer" to a number. But references can't be null so we can;t use nullptr either. So there is no valid default value initialization for the reference. The only reasonable thing is then to delete the default constructor because there does not exist any default value we can use to initialize one of its members.

How to declare the of size of a data structure in header (C++) [duplicate]

Suppose I have a unique_ptr member object that I want to initialize in-class, see the code below. Why do I have to use uniform initialization (curly braces)? The second declaration spits an error, something like
so.cpp:10:31: error: expected parameter declarator
std::unique_ptr<Foo> upf2(new Foo);
^
so.cpp:10:31: error: expected ')'
so.cpp:10:30: note: to match this '('
std::unique_ptr<Foo> upf2(new Foo); ^
2 errors generated.
And I don't think is a most vexing parse issue, at least I don't believe so.
#include <memory>
class Foo
{
};
class Bar{
std::unique_ptr<Foo> upf1{new Foo}; // works fine
// std::unique_ptr<Foo> upf2(new Foo); // error here
};
int main()
{
Bar bar;
}
Because those are the rules. In-class initialisers must use "braces" or "equals"; in fact, the syntactical element is called a brace-or-equal-initializer.
int equals = 42; // OK
std::unique_ptr<Foo> braces{new Foo}; // Also OK
I don't know why parentheses aren't allowed; perhaps to avoid the possibility of the initialisation looking like a function declaration. It can be annoying when there's a difference between direct and brace initialisation:
std::vector<int> bad(6); // ERROR: parentheses not allowed
std::vector<int> good{6}; // OK but not the same
std::vector<int> ugly = std::vector<int>(6); // OK but ugly
A non-static data member initializer (NSDMI) must use a brace-or-equal-initializer. The ( expression-list ) form of initialization isn't allowed.
As N2756 explains, in order to allow NSDMIs to behave more like traditional constructor member initializer lists, the names inside initializers are looked up in the scope of the entire class. Unfortunately, this means that allowing parentheses initializers would make it impossible to determine whether something is an initializer or a function declaration at the time the declaration is parsed:
// not real code
struct X {
int i(x); // initializer
static int x;
};
struct Y {
int i(x); // function
typedef int x;
};
The paper discussed a couple possible ways to fix this short of banning it altogether ("everything that can be a declaration is a declaration" or "it's not a type unless you say it's a type"), but neither is very appealing, and the potential confusion was deemed to outweigh the benefit of allowing this form of initialization.

C++ default argument constructor vs inline initialisation priority

Is the variable here 1 or 2 and is this compiler or standard dependent?
class foo {
int val = 1;
foo(int bar = 2) : val(bar) {}
}
It is 2 unless you provide a different value when calling the constructor.
See cpp reference concerning non-static data member initialisation:
If a member has a default member initializer and also appears in the
member initialization list in a constructor, the default member
initializer is ignored.
this here : foo(int bar = 2) is called default argument,
and allows you to call a function without providing that argument.
How?
if you do:
foo(100) then val is initialized with 100
but if you ommit the parameter
foo( ) then val is initialized with 2
at the end, that declaration makes this init superfluous:
int val = 1;

Unique pointer in-class initialization

Suppose I have a unique_ptr member object that I want to initialize in-class, see the code below. Why do I have to use uniform initialization (curly braces)? The second declaration spits an error, something like
so.cpp:10:31: error: expected parameter declarator
std::unique_ptr<Foo> upf2(new Foo);
^
so.cpp:10:31: error: expected ')'
so.cpp:10:30: note: to match this '('
std::unique_ptr<Foo> upf2(new Foo); ^
2 errors generated.
And I don't think is a most vexing parse issue, at least I don't believe so.
#include <memory>
class Foo
{
};
class Bar{
std::unique_ptr<Foo> upf1{new Foo}; // works fine
// std::unique_ptr<Foo> upf2(new Foo); // error here
};
int main()
{
Bar bar;
}
Because those are the rules. In-class initialisers must use "braces" or "equals"; in fact, the syntactical element is called a brace-or-equal-initializer.
int equals = 42; // OK
std::unique_ptr<Foo> braces{new Foo}; // Also OK
I don't know why parentheses aren't allowed; perhaps to avoid the possibility of the initialisation looking like a function declaration. It can be annoying when there's a difference between direct and brace initialisation:
std::vector<int> bad(6); // ERROR: parentheses not allowed
std::vector<int> good{6}; // OK but not the same
std::vector<int> ugly = std::vector<int>(6); // OK but ugly
A non-static data member initializer (NSDMI) must use a brace-or-equal-initializer. The ( expression-list ) form of initialization isn't allowed.
As N2756 explains, in order to allow NSDMIs to behave more like traditional constructor member initializer lists, the names inside initializers are looked up in the scope of the entire class. Unfortunately, this means that allowing parentheses initializers would make it impossible to determine whether something is an initializer or a function declaration at the time the declaration is parsed:
// not real code
struct X {
int i(x); // initializer
static int x;
};
struct Y {
int i(x); // function
typedef int x;
};
The paper discussed a couple possible ways to fix this short of banning it altogether ("everything that can be a declaration is a declaration" or "it's not a type unless you say it's a type"), but neither is very appealing, and the potential confusion was deemed to outweigh the benefit of allowing this form of initialization.

Initialize static constant member variable in nested class

Given codes in language C++
/* file xxx.hpp */
class A
{
};
class B
{
private:
class C
{
static const A a;
};
};
How can I initialize the static constant member variable A a in nested class C?
Add the following to exactly one .cpp:
const A B::C::a;
Note that the posted code was only a declaration: this is the actual definition and initialisation.
In the cpp file with code that is to be compiled you should add const A B::C::a = {};.
The initializer (be it an initializer list in {...} for POD classes or aggregate types or a single constant value for built-in types) is optional - if it's not specified, a default constructor will be called for a. In case of primitive types, it should be set to 0.
updated:
As David has greatly remarked below, some compilers issue warnings when no initializer is specified for a static member definition. If there are some data members in class A and no initializer during definition of a is specified, my g++ 4.6.3 compiler issues the following warning (that is by default is treated as error):
test.cpp:26:9: error: uninitialized const ‘B::C::a’ [-fpermissive]
test.cpp:6:7: note: ‘const class A’ has no user-provided default
constructor test.cpp:11:8: note: and the implicitly-defined constructor does not initialize ‘int A::test’
Like you would a regular static member.
In your implementation file:
const A B::C::a;
Initialization of static member variables is always performed in the definition of the variable, which has to be in a single translation unit within your program:
const A B::C::a = {};
In the source file (xxx.cpp), define the variable:
const A B::C::a;