Avoiding construction of object fields

I have made the following code to illustrate my problem:
1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once

#include <bitset>
#include <iostream>

class ConstructTest
{
	private:
		std::bitset<5> bitset = NULL;
	public:
		ConstructTest();
		~ConstructTest();
};

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "ConstructTest.h"

ConstructTest::ConstructTest()
{
	std::cout << (bitset == NULL) << std::endl;
	std::cout << bitset << std::endl;
	std::cout << bitset.to_string() << std::endl;
	std::cout << (bitset == NULL) << std::endl;
	bitset.set(1);
	std::cout << bitset << std::endl;
}

ConstructTest::~ConstructTest() {}

1
2
3
4
5
6
7
#include "ConstructTest.h"

int main()
{
	ConstructTest t;
	return 0;
}


Now I want to avoid my bitset field being constructed before the ConstructTest constructor is called. So at first I tried wrapping it in a unique_ptr but found out that this would give me some potential problems with const functions.

And then I realized I could just set it to NULL, as I have in the above code. I tried that, got unexpected print outs, until I found out that NULL is just equal to 0 in C++ and that the bitset has a = operator that takes a number, int, long or maybe something else. Either way, this effectively constructs the bitset and sets it to the number 0.

So my efforts so far have been shut down. But then how can I avoid the bitset being constructed in advance, if at all possible?
You can't. All members must be constructed before the constructor is called.
If you need to pass parameters to the constructor that depend on the values of other members that must be constructed first, you can declare those members first in the class; the order of construction is the order of declaration. Then you pass whatever you need to pass in the initialization list.
> I want to avoid my bitset field being constructed before the ConstructTest constructor is called.

The non-static member is constructed after the ConstructTest constructor is invoked, but before the compound-statement of the constructor body is executed.


> how can I avoid the bitset being constructed in advance, if at all possible?

To prevent the bitset being constructed before the compound-statement of the constructor body is executed, declare it as a member of a union.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <bitset>
#include <new>

struct construct_test
{
    using bitset_type = std::bitset<5> ;

    construct_test()
    {
        std::cout << "in construct_test::constructor: about to construct bitset\n" ;
        new(&c) bitset_type( "10101" ) ; // construct with placement new
        std::cout << "constructed bitset: bitset == " << bitset << '\n' ;
    }

    construct_test( const construct_test& that ) : bitset(that.bitset) {}
    construct_test( construct_test&& that ) noexcept : bitset( std::move(that.bitset) ) {}
    construct_test& operator= ( const construct_test& that ) { bitset = that.bitset ; return *this ; }
    construct_test& operator= ( construct_test&& that ) noexcept { bitset = std::move(that.bitset) ; return *this ; }

    ~construct_test()
    {
        std::cout << "in construct_test::destructor: about to destroy bitset\n"   ;
        bitset.~bitset_type() ; // destroy with explicit call of destructor
        std::cout << "destroyed bitset\n" ;
    }

    private:
        union
        {
            char c ;
            bitset_type bitset ;
        };
};

int main()
{
    construct_test ct ;
}

http://coliru.stacked-crooked.com/a/92b9772f95756536
Thanks helios. As it turns out though, that the bitset is constructed before the constructor call may not be a problem, as I have noticed that the bitset has the same address before and after an assignment in the constructor, as seen in this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once

#include <bitset>
#include <iostream>

class ConstructTest
{
	private:
		std::bitset<5> bitset = NULL;
	public:
		ConstructTest();
		~ConstructTest();
};


1
2
3
4
5
6
7
8
9
10
#include "ConstructTest.h"

ConstructTest::ConstructTest(string binary)
{
	std::cout << &bitset << std::endl;
	bitset = bitset<5>(binary);
	std::cout << &bitset << std::endl;
}

ConstructTest::~ConstructTest() {}


So it seems to me that the assignment operator just sets the bits in the bitset already present in the variable. But am I still not creating a new bitset when assigning the variable? If so, that seems like a waste of a bitset every time I create a ConstructTest object, but is there then another way of assigning the bits in the string to the bitset without creating a new bitset and assigning that to the variable?
I have noticed that the bitset has the same address before and after an assignment in the constructor
Well, yeah. The same is true for any class member.

But am I still not creating a new bitset when assigning the variable?
A temporary may be created on the stack and then destroyed. Probably no memory allocation takes place.

If so, that seems like a waste of a bitset every time I create a ConstructTest object, but is there then another way of assigning the bits in the string to the bitset without creating a new bitset and assigning that to the variable?
Well, you can decompose the string and assign each bit manually if you care about those things. I wouldn't bother until there's evidence that it causes a performance problem.
Knuth said it best: Premature optimization is the root of all evil.

The fact that you're passing the string by value is probably much worse.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <bitset>
#include <string>
#include <iostream>

class ConstructTest
{
	private:
		std::bitset<5> bitset ; // = NULL;
	public:
		ConstructTest( const std::string& binary );
		//~ConstructTest();
};

ConstructTest::ConstructTest( const std::string& binary ) : bitset(binary) // ***
{
	// std::cout << &bitset << std::endl;
	// bitset = bitset<5>(binary);
	// std::cout << &bitset << std::endl;
        std::cout << bitset << '\n' ;
}

// ConstructTest::~ConstructTest() {}

int main()
{
    ConstructTest ct( "10101" ) ;
}
Topic archived. No new replies allowed.