2013-09-06 6 views
12

Привет, Я создал класс Foo с конструктором move noexcept с использованием gcc 4.7 и установил векторный размер резервной копии в 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 build не запускает копию ctor один раз. получить более умный gcc? – WhozCraig

+1

Он работает как ожидалось (то есть 'vector' вызывает конструктор перемещения) с GCC 4.8.1. –

+2

Он отлично работает с [gcc 4.8.1] (http://ideone.com/SXoMw2). Может быть ошибка в 4.7 – Angew

ответ

13

После возиться с ним немного с обоими GCC 4.7 и 4.8, кажется, что это действительно ошибка в 4.7, который появляется только тогда, когда деструктор класса не отмечен noexcept:

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 дисплеи:

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 для деструктора. GCC 4.8 правильно делает деструктор noexcept, как требуется C++ 11.' –

Смежные вопросы

 Смежные вопросы