This question already has answers here:
Is it defined behavior to reference an early member from a later member expression during aggregate initialization?
(4 answers)
Closed 4 years ago.
Is it legal to do the following?
#include <iostream>
struct Foo
{
int bar;
int baz;
};
int main()
{
Foo instance = { 5, instance.bar };
std::cout << instance.baz << std::endl;
}
I think it's not because as far as I know the order of initialization is unspecified and the bar field can be initialized after baz.
Am I right?
https://coliru.stacked-crooked.com/a/ea97713515dd0687
If you liked your conundrum, this is really gonna bake your noodle:
#include <iostream>
struct Foo
{
int bar=0;
int baz=1;
};
const int cool(const Foo& f)
{
std::cout << "Bar: " << f.bar << " Baz: " << f.baz << std::endl;
return f.bar;
}
int main()
{
Foo instance = { 5, cool(instance) };
std::cout << instance.baz << std::endl;
}
What a previous poster correctly quoted: c++ std draft doc
...all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.
Related
This question already has answers here:
Is it defined behavior to reference an early member from a later member expression during aggregate initialization?
(4 answers)
Closed 1 year ago.
Is it correct to use the member of a struct that we are initializing? My compiler does not complain with the following code:
#include <iostream>
struct Foo {
int a, b;
};
int main() {
Foo foo {34, foo.a + 2}; // I'm using `foo.a` during the `foo` initialization
std::cout << foo.a << " " << foo.b << std::endl;
return 0;
}
// Prints "34 36"
But it seems weird since foo is not declared yet when I use it inside the braces.
This is fine and valid as long as you keep a declared before b as you're doing right now.
This question already has answers here:
What's the point of g++ -Wreorder?
(5 answers)
Closed 2 years ago.
I am reading into Scott Meyers book Effective c++. For constructors he recommends initialization of object data in a specific order.
Base class before derived class
Within a class data members initialized in the order which the are declared.
Appearantly not following these rules can lead to obscure behavioral bugs ... However he does'nt give any examples or go into details.
Can you give an example of what kind of bugs can occur?
For example,
struct S
{
int a;
int b;
S() : b(42), a(b + 1) {}
};
leads to undefined behavior:
As contrary as we might expect from constructor,
a is initialized before b (according to member order).
It can confusing to have the wrong order:
struct foo {
int a;
int b;
foo(int x) : b(++x),a(++x) {
std::cout << "a = " << a <<'\n';
std::cout << "b = " << b <<'\n';
}
};
Constructing a foo(1) prints:
a = 1
b = 2
Not a = 2, b = 1 as one might expect from the order of the initializer list. Real problems can occur if initialization of one member depends on another member. This is correct (but not nice):
struct bar {
int a;
int b;
bar() : b(a),a(1){
std::cout << "a = " << a <<'\n';
std::cout << "b = " << b <<'\n';
}
};
Prints:
a = 1
b = 1
And this invokes undefined behavior:
struct broken {
int a;
int b;
broken() : b(1),a(b){
std::cout << "a = " << a <<'\n';
std::cout << "b = " << b <<'\n';
}
};
Can you give an example of what kind of bugs can occur?
class foo
{
int *ptr;
int size;
public:
foo() : size(10), ptr(new int[size]) {}
};
int main()
{
foo f;
}
See the warnings here.
The size is initialized after the ptr is initialized, thus size is actually some random value when new is issued to allocate dynamically.
This question already has answers here:
Initialization Order of Class Data Members
(2 answers)
Closed 3 years ago.
I'm trying to understand member class initialization order but there is one thing that confusing me.
#include <iostream>
class Foo {
int y{7};
public:
Foo()
{
std::cout << "Foo Constructor";
}
explicit Foo(int yy) : y(yy)
{
std::cout << "Foo " << y << std::endl;
}
int gety()
{
std::cout << "Foo::gety() returning ";
return y;
}
};
class Bar {
int x;
public:
Bar()
{
std::cout << "Bar constructor" << std::endl;
}
explicit Bar(int xx) : x(xx)
{
std::cout << "Bar "<< x << std::endl;
}
int getx()
{
std::cout << "Bar::getx() returning ";
return x;
}
};
class Class {
Bar bar;
Foo foo;
public:
Class() : bar(foo.gety()), foo(5)
{
std::cout << "Class()\n";
}
void printxy()
{
std::cout << "Bar.x = " << bar.getx() << " \n" << "Foo.y = " << foo.gety() << std::endl;
}
};
int main(void)
{
Class k;
k.printxy();
return 0;
}
I'm compiling this code with gcc --std=c++11 -Wuninitialized -Wall -pedantic
In Class object there is two members of class Foo and Bar. In initialization list I'm constructing firs bar object by using constructor that takes int as argument. But as i understand foo is not constructed yet because it's second in order on initialization list. So how i don't get any errors when using foo.gety() before it's constructed?
I think C++ is guarantee that any used object is constructed. So when Foo object is constructed? Or this is undefined behavior?
This is link for coliru example: Link
Member variables are initialized in the order they are defined in the class. In your case bar will be initialized before foo (even if you change the order in the constructor initializer list).
What you're doing, using the uninitialized foo object, will lead to undefined behavior. There's no guarantee that a compiler will be able to catch it or even report it.
In order to store a non-type template parameter inside the instance of a class, I often see either a static constexpr data member, or an enum declaration, as illustrated in the code below.
These two solutions seem equivalent when using them in simple case as in the main() function here.
This raises two questions:
1. Is there any operation we can do with one solution that we cannot do with the other?
2. Which versions of C++ allow or forbid these solutions?
#include <iostream>
// solution 1
template<int _i>
struct Foo
{
static constexpr int i = _i;
};
// solution 2
template<int _i>
struct Bar
{
enum
{
i = _i
};
};
int main()
{
Foo<1> foo;
Bar<2> bar;
std::cout << foo.i << std::endl;
std::cout << bar.i << std::endl;
std::cout << Foo<3>::i << std::endl;
std::cout << Bar<4>::i << std::endl;
return 0;
}
This question already has answers here:
Why can I use auto on a private type?
(5 answers)
Closed 9 years ago.
Let's consider the next code:
#include <iostream>
#include "mydemangled.hpp"
using namespace std;
struct A
{
private:
struct B {
int get() const { return 5; }
};
public:
B get() const { return B(); }
};
int main()
{
A a;
A::B b = a.get();
cout << demangled(b) << endl;
cout << b.get() << endl;
}
And the compiler (gcc 4.7.2) yells saying that A::B is private. All right.
So, I change the code:
int main()
{
A a;
cout << demangled(a.get()) << endl;
cout << a.get().get() << endl;
}
and it doesn't yell:
$ ./a.out
A::B
5
Meaning, I can't to create instances of A::B, but I can use it.
So, new change (the key of my question).
int main()
{
A a;
auto b = a.get();
cout << demangled(b) << endl;
cout << b.get() << endl;
}
And output:
$ ./a.out
A::B
5
What is the trouble here, being A::B private (and thus its constructors, copy constructors and so on)?
In general, access controls names or symbols, not the
underlying entities. There are, and always have been, numerous
ways of accessing private members; what you cannot do is use the
name of such a member.
In your examples, you don't use the name, so there is no
problem.