2013-09-06 2 views
12

こんにちは、gcc 4.7を使用してnoexcept移動コンストラクタでFooクラスを作成し、3番目のアイテムを追加するときにサイズを再割り当てする必要があるようにベクトル確保サイズを2に設定しました。これは、移動コンストラクタの代わりにコピーコンストラクタを呼び出すようです。私はここに何かを逃していますかベクトル再配置では、移動コンストラクタの代わりにコピーが使用されます

#include <vector> 
#include <iostream> 

class Foo 
{ 
    public: 
    Foo(int x) : data_(x) 
    { 
    std::cout << " constructing " << std::endl; 
    } 

    ~Foo() 
    { 
    std::cout << " destructing " << std::endl; 
    } 

    Foo& operator=(const Foo&) = default; 
    Foo& operator=(Foo&&) = default; 

    Foo(Foo&& other) noexcept : data_(std::move(other.data_)) 
    { 
    std::cout << " Move constructing " << std::endl; 
    } 

    Foo(const Foo& other) noexcept : data_(other.data_) 
    { 
    std::cout << " Copy constructing " << std::endl; 
    } 

    private: 
    int data_; 
}; 


int main (int argc, char *argv[]) 
{ 
    std::vector<Foo> v; 
    v.reserve(2); 
    v.emplace_back(1); 
    std::cout << "Added 1" << std::endl; 
    v.emplace_back(2); 
    std::cout << "Added 2" << std::endl; 
    v.emplace_back(3); 
    std::cout << "Added 3" << std::endl; 
    std::cout << "v size: " << v.size() << std::endl; 
} 

出力:

constructing 
Added 1 
constructing 
Added 2 
constructing 
Copy constructing 
Copy constructing 
destructing 
destructing 
Added 3 
v size: 3 
destructing 
destructing 
destructing 
+1

私のclangビルドはコピーctorを一度起動しません。よりスマートなgccを手に入れる? – WhozCraig

+1

GCC 4.8.1で期待通りに動作します(つまり、 'vector'は移動コンストラクタを呼び出します)。 –

+2

[gcc 4.8.1](http://ideone.com/SXoMw2)とうまく動作します。 4.7 – Angew

答えて

13

それを両方GCC 4.7と4.8と少しいじった後、確かにクラスのデストラクタがある場合にのみ表示されます4.7のバグ、あるようです

struct Foo { 
    Foo() {} 
    ~Foo() noexcept {} 
    Foo(Foo&&) noexcept { std::cout << "move constructor" << std::endl; } 
    Foo(const Foo&) noexcept { std::cout << "copy constructor" << std::endl; } 
}; 

int main() { 
    std::vector<Foo> v; 
    v.reserve(2); 
    v.emplace_back(); 
    v.emplace_back(); 
    v.emplace_back(); 
} 

GCC 4.7が表示されます:ないnoexceptをマークし

move constructor 
move constructor 

我々はデストラクタからnoexceptを削除する場合:

struct Foo { 
    Foo() {} 
    ~Foo() {} 
    Foo(Foo&&) noexcept { std::cout << "move constructor" << std::endl; } 
    Foo(const Foo&) noexcept { std::cout << "copy constructor" << std::endl; } 
}; 

GCC 4.7が表示されます。

copy constructor 
copy constructor 

GCC 4.8の両方のケースで移動コンストラクタを使用しています。

+9

+1 [バグを発見](http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56191)。 'G ++ 4.7はデストラクタがnoexceptであるという規則を適用しないので、デストラクタに明示的なnoexcept指定を追加する必要があります。 GCC 4.8は、C++ 11で必要とされるようにnoexceptをデストラクタに正しく行います.' –

関連する問題