开发者

In place constrution of member variable via constructor

开发者 https://www.devze.com 2023-02-26 18:56 出处:网络
Take the following class: template <typename TPayload> class Message { public: Message(const TPayload& payload)

Take the following class:

template <typename TPayload>
class Message
{
    public:
        Message(const TPayload& payload)
             : m_header(sizeof(TPayload)),
               m_payload(payload) {}

    private:
        const Header   m_header;
        const TPayload m_payload;
};

Whenever I construct a Message I have to create a TPayload (the parameter payload), copy this into m_payload, and then destruct payload. Now consider this can be done 100'000s of times a second, I think this is a 开发者_Go百科wasted effort.

My question is, can I force an inplace construction of m_payload to avoid the tempory payload?

One possible solution I am considering is overloading the construction many times like below but to be honest with all the copying of the multiple argumwents I'm doubting there is much saving.

template <typename TPayload>
class Message
{
    public:
        template <typename A>
        Message(const A& a)
             : m_header(sizeof(TPayload)),
               m_payload(a) {}

        template <typename A, typename B>
        Message(const A& a, const B& b)
             : m_header(sizeof(TPayload)),
               m_payload(a, b) {}

    private:
        const Header   m_header;
        const TPayload m_payload;
};


What you're looking for is forwarding of constructor arguments given to Message to the constructor of Message::m_payload.

This can be done neatly in C++11 (using variadic templates and std::forward, as used in std::vector<>::emplace_back() and many other functions) or with several overloads in C++03, as you started writing, and as used in boost::make_shared<>

for example:

#include <iostream>
#include <string>
#include <utility>
typedef size_t Header;
template <typename TPayload>
class Message
{
    public:
        template <typename ...Args>
        Message(Args&&... args)
             : m_header(sizeof(TPayload)),
               m_payload(std::forward<Args>(args)...)
               {}
        void show_payload() const
        {
                std::cout << m_payload << '\n';
        }
    private:
        const Header   m_header;
        const TPayload m_payload;
};

int main()
{
     Message<std::string> test(10, 'a');
     test.show_payload();

     Message<double> test2(3.14);
     test2.show_payload();
}

test run: https://ideone.com/J1JnZ


Also in C++11, you can accept the parameter by value, then move construct it:

Message(TPayload payload)
    :m_header(sizeof(TPayload)),
     m_payload(std::move(payload)) {}

Just make sure TPayload has a properly defined and useful move constructor, otherwise this won't do much good.

0

精彩评论

暂无评论...
验证码 换一张
取 消