0

新しいコンテナが定義されている場合は、次のコードを検討してください。std::array

#include <iostream>
#include <array>
#include <initializer_list>

// My container
template<typename Type, unsigned int Size>
class MyContainer
{
    // Lifecycle
    public:
        MyContainer() : _data() {}
        MyContainer(const MyContainer<Type, Size>& rhs) : _data(rhs.data()) {}
        MyContainer(const std::array<Type, Size>& rhs) : _data(rhs) {}
        template<typename... Types> MyContainer(const Types&... numbers) : _data({{numbers...}}) {}
        ~MyContainer() {}

    // Assignment
    public:
        MyContainer<Type, Size>& operator=(const MyContainer<Type, Size>& rhs) {_data = rhs.data(); return *this}

    // Accessors
    public:
        Type& operator[](const unsigned int i) {return _data[i];}
        const Type& operator[](const unsigned int i) const {return _data[i];}
        std::array<Type, Size>& data() {return _data;}
        const std::array<Type, Size>& data() const {return _data;}

    // Operators
    public:
        MyContainer<Type, Size> operator+(const MyContainer<Type, Size>& rhs)
        {
            MyContainer<Type, Size> result;
            for (unsigned int i = 0; i < Size; ++i) {
                result[i] = _data[i] + rhs[i];
            }
            return result;
        }

    // Data members
    protected:
        std::array<Type, Size> _data;
};

// Main
int main(int argc, char* argv[])
{
    // Initialization
    MyContainer<double, 4> x = {0., 1., 2., 3.};
    MyContainer<double, 4> y = {4., 5., 6., 7.};
    MyContainer<double, 4> z;

    // Operation
    z = x+y; // Can move semantics help here ?

    // Result
    std::cout<<z[0]<<" "<<z[1]<<" "<<z[2]<<" "<<z[3]<<std::endl;
    return 0;
}

セマンティクスを移動すると、いくつかのコピーを回避することで main() の操作を高速化できますか?

答えが「はい」の場合、現在の設計にどのように実装しますか?

4

2 に答える 2

2

いいえ。 a のすべてのデータはstd::array<double, N>、オブジェクト自体に含まれています。移動セマンティクスは、オブジェクトが (通常はポインターを介して) 外部参照リソースを所有し、その参照をコピーして無効にすることができる場合にのみ役立ちます。

于 2013-01-05T01:43:17.897 に答える
0

aMyContainer<double>を「移動」すると、double実際にはコピーが行われますdouble。a には移動するリソースがなく、コピーする値しかないため、利点はありません。

しかし、あなたの型はテンプレートなので、おそらくdouble. MyContainer<std::string>または、MyContainer<HeavyweightType>移動操作を定義する価値があります。それは簡単です:

    MyContainer(MyContainer&&) = default;
    MyContainer& operator=(MyContainer&&) = default;

MyContainerの代わりにMyContainer<Type, Size>、クラス テンプレートの定義で、テンプレート引数リストのないクラス テンプレートの名前は、現在のインスタンス化を参照する、つまりMyContainerと同じ型であると言うことができることに注意してくださいMyContainer<Type, Size>

他の特別なメンバー関数の一部も単純化できます。

    MyContainer(const MyContainer&) = default;
    ~MyContainer() = default;

    MyContainer& operator=(const MyContainer>&) = default;

これで、適切なセマンティクスを備えた型が移動およびコピー可能になり、コードは元のバージョンよりもさらに単純になりました。

これらの関数に移動サポートを追加することもできます。

    MyContainer(const std::array<Type, Size>& rhs) : _data(rhs) {}
    template<typename... Types> MyContainer(const Types&... numbers) : _data({{numbers...}}) {}

rvalue を受け取るコンストラクターを追加し、コンストラクarrayター テンプレートでユニバーサル参照と完全転送を使用するようにします。

    MyContainer(const std::array<Type, Size>& rhs) : _data(rhs) {}
    MyContainer(std::array<Type, Size>&& rhs) : _data(std::move(rhs)) {}
    template<typename... Types> MyContainer(Types&&... numbers)
      : _data{{ std::forward<Types>(numbers)...}} {}

これで、型を右辺値で初期化できます。

于 2013-01-06T13:59:17.070 に答える