9

私はC++ Primer 5th Editionから演習を行っています。これは次のようになります。

演習 13.50: Stringクラスの移動操作に print ステートメントを配置し、ベクトルを使用した§ 13.6.1 (p. 534) の演習 13.48 からプログラムを再実行して、コピーがいつ回避されるかを確認します。(P.544)

はテンプレートを使わずStringに のように振る舞う練習用のクラスです。ファイルstd::string:String.h

class String
{
public:
    //! default constructor
    String();

    //! constructor taking C-style string i.e. a char array terminated with'\0'.
    explicit String(const char * const c);

    //! copy constructor
    explicit String(const String& s);

    //! move constructor    
    String(String&& s) noexcept;

    //! operator =
    String& operator = (const String& rhs);

    //! move operator =     
    String& operator = (String&& rhs) noexcept;

    //! destructor
    ~String();

    //! members
    char* begin() const  { return elements;   }
    char* end()   const  { return first_free; }

    std::size_t size()     const {return first_free - elements;  }
    std::size_t capacity() const {return cap - elements;         }

private:

    //! data members
    char* elements;
    char* first_free;
    char* cap;

    std::allocator<char> alloc;

    //! utillities for big 3
    void free();

};

デフォルトの実装、コピーおよび移動コンストラクタ from String.cpp:

//! default constructor
String::String():
    elements    (nullptr),
    first_free  (nullptr),
    cap         (nullptr)
{}

//! copy constructor
String::String(const String &s)
{
    char* newData = alloc.allocate(s.size());
    std::uninitialized_copy(s.begin(), s.end(), newData);

    elements = newData;
    cap = first_free = newData + s.size();

    std::cout << "Copy constructing......\n";
}

//! move constructor    
String::String(String &&s) noexcept :
    elements(s.elements), first_free(s.first_free), cap(s.cap)
{
    s.elements = s.first_free = s.cap = nullptr;
    std::cout << "Move constructing......\n";
}

Main.cpp:

int main()
{
    std::vector<String> v;
    String s;
    for (unsigned i = 0; i != 4; ++i)
        v.push_back(s);

    return 0;
}

出力:

Copy constructing......
Copy constructing......
Copy constructing......
Copy constructing......
Copy constructing......
Copy constructing......
Copy constructing......

ご覧のとおり、move コンストラクターはまったく呼び出されていません。ベクトルがより多くのメモリを割り当てているときに、move コンストラクターが呼び出されなかったのはなぜですか?

アップデート:

コンパイラの情報:

gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-1ubuntu1) 

main.cpp印刷能力とその出力:

int main()
{
    std::vector<String> v;
    String s;
    for (unsigned i = 0; i != 4; ++i)
    {
        std::cout << v.capacity() << "\n";
        v.push_back(s);
    }

    return 0;
}

出力:

0
Copy constructing......
1
Copy constructing......
Copy constructing......
2
Copy constructing......
Copy constructing......
Copy constructing......
4
Copy constructing......
4

1 に答える 1

1

MinGWのgcc 4.7.1で再現します...

追加~String() noexceptすると問題が解決します...

于 2014-01-07T10:16:21.920 に答える