【问题标题】:Why wasn't the move constructor called? [duplicate]为什么不调用移动构造函数? [复制]
【发布时间】:2014-01-24 21:44:01
【问题描述】:

我正在做一个 C++ Primer 5th Edition 的练习,类似于:

练习 13.50:将打印语句放入你的移动操作中 String 类并从第 13.6.1 节中的练习 13.48 重新运行程序(p. 534)使用 vector 来查看何时避免复制。(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();

};

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......

可以看出,移动构造函数根本没有被调用。为什么向量分配更多内存时不调用移动构造函数?

更新:

编译器信息:

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......

【问题讨论】:

  • Works for me,一旦我添加了足够多的缺失定义来编译它。您使用的是哪个编译器?检查向量的容量 - 可能它会预先为四个或更多元素预留空间?
  • 这是哪个编译器?在 gcc 中工作(4.7.2 和 4.8.2 - 只有我现在可以访问的...)
  • @MikeSeymour 4.73 我已经更新了线程,增加了打印容量。
  • @Nim 4.73 我更新了线程,增加了打印容量。
  • 投票结束,该问题将被标记为已结束,其他人也将投票结束,然后问题将被关闭。但是不要删除它,因为关于这是一个 gcc 错误的信息在另一个问题中也不是很突出。

标签: c++ c++11 stl constructor move-constructor


【解决方案1】:

我在 MinGW 上使用 gcc 4.7.1 重现...

添加~String() noexcept 可以解决问题...

【讨论】:

    猜你喜欢
    • 2015-06-10
    • 1970-01-01
    • 2013-04-25
    • 2012-04-29
    • 1970-01-01
    相关资源
    最近更新 更多