【问题标题】:c++ move semantics clarificationc++ move语义澄清
【发布时间】:2014-07-31 08:00:37
【问题描述】:

我有一个包含 std::string 的 Text 类。一个方法 SetText 如下:

void Text::SetText( const std::string& str )
{
    m_str = str;
}

由于这个方法几乎总是以右值作为参数调用,所以我考虑了移动构造函数。我了解基础知识,但仅此而已。所以我做了测试,得出的结论是,另一个这样的函数会更好,一旦定义了移动构造函数和移动赋值,就会有性能提升:

void Text::SetText( std::string&& str )
{
    m_str = move( str );
}

有我的问题:

  • 它是否适用于标准容器?他们是否提供移动构造函数和赋值?
  • 当类没有堆分配时,移动语义有用吗? (我的意思是根本没有堆分配,所以没有智能指针作为类成员)

谢谢。

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    您的代码是正确的。但首选的 C++11 方法是:

    void Text::SetText(std::string str)
    {
        m_str = move(str);
    }
    

    也就是说,按值传递并从中移动。

    如果你传递一个右值和一个副本,这将适用于移动,如果你传递一个左值,则一个移动,在后一种情况下,一个副本是必要的。

    它是否适用于标准容器?他们是否提供移动构造函数和赋值?

    是的,标准库为所有类提供了移动构造函数和移动赋值,使其比复制更有效。

    当类没有堆分配时,移动语义有用吗? (我的意思是根本没有堆分配,所以没有智能指针作为类成员)

    除了少数使用其他资源的情况外,没有。

    如果对象的所有数据都直接存储在对象中,它们必须被复制,没有其他工作可以通过移动来保存。

    还请注意,如果您使函数内联,编译器应该能够在右值情况下省略其中一个动作。除非operator= 也被内联,否则它不能在左值情况下省略它,因为它不允许用复制赋值替换移动赋值。

    【讨论】:

    • 有什么特别的原因你不std::swap(m_str, str)
    • 提供void Text::SetText( std::string&& str )重载也是正确的。
    • @TNA: 是的,但是你需要 both std::string && std::string const & 重载并且不会得到太多好处。跨度>
    • 使用 void Text::SetText(std::string str),如果它是左值,它会进行复制,对吗?避免复制不是更好吗?
    • @Aulaulz:如果你传递一个左值,就会有一个无法避免的副本。你可以在参数中(通过值传递,这需要额外的移动)或在赋值(通过引用,需要两个重载)中这样做,但你不能避免它。
    猜你喜欢
    • 2013-09-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 1970-01-01
    相关资源
    最近更新 更多