试图使用c ++移动构造函数......并失败

时间:2015-02-13 12:51:45

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

当我以为我理解了std :: move和move构造函数的作用时,我试着编写一些单元测试,实际测试某些类的移动构造函数...

令我惊讶的是,我发现,我无法想出构建实际调用移动构造函数的代码的方法。更糟糕的是,我甚至无法在移动构造函数的主体中设置断点(在VS2013社区版,调试,64位构建中)。

想知道这是否是编译器的特性,我使用clang(3.4.1)在我的freebsd虚拟机上敲了一些小测试代码。在那里,我也找不到调用移动构造函数的方法。

#include <iostream>
#include <stdint.h>
#include <string>
#include <algorithm>
#include <functional>
#include <ctype.h>
#include <locale>

void InPlaceToUpper( std::string& target )
{
    std::transform(target.begin(), target.end(), target.begin(), ::toupper);
}
void InPlaceToLower( std::string& target )
{
    std::transform(target.begin(), target.end(), target.begin(), ::tolower);
}

std::string ToUpper( const std::string& s )
{
    std::string result;
    result.resize(s.length());
    std::transform(s.begin(), s.end(), result.begin(), ::toupper);
    return result;
}
std::string ToLower( const std::string& s)
{
    std::string result;
    result.resize(s.length());
    std::transform(s.begin(), s.end(), result.begin(), ::tolower);
    return result;
}


class CFoo
{
    std::string m_value;
public:
    CFoo()
        : m_value()
    {
        std::cout << "CFoo() called." << std::endl;
    }
    CFoo(const char *value)
        : m_value(value)
    {
        std::cout << "CFoo(const char *) called." << std::endl;
    }
    CFoo(const std::string& value )
         : m_value(value)
    {
        std::cout << "CFoo(const std::string&) called." << std::endl;
    }
    CFoo(const CFoo& other )
        : m_value(other.m_value)
    {
        std::cout << "CFoo() copy constructor called." << std::endl;
    }
    CFoo(CFoo&& other )
        : m_value(std::move(other.m_value))
    {
        std::cout << "CFoo() move constructor called." << std::endl;
        std::cout << "other.m_value = " << other.m_value.c_str() << std::endl;
    }
    ~CFoo()
    {
        std::cout << "~CFoo() called." << std::endl;
    }
    const CFoo& operator=( const CFoo& other )
    {
        std::cout << "CFoo copy assignment operator called." << std::endl;
        if( &other != this )
        {
            m_value = other.m_value;
        }
        return *this;
    }
    const CFoo& operator=( CFoo&& other )
    {
        std::cout << "CFoo move assignment operator called." << std::endl;
        if( &other != this )
        {
            m_value = std::move(other.m_value);
        }
        return *this;
    }
    CFoo ToUpper()
    {
        return CFoo(::ToUpper(m_value));
    }
    CFoo ToLower()
    {
        return CFoo(::ToLower(m_value));
    }
    const char * ToString() const
    {
        return m_value.c_str();
    }
};

int main( int argc, const char *argv[] )
{
    {
        CFoo foo;
        CFoo foo1("Hello World");
        CFoo foo2 = CFoo("Hello again World!");
        CFoo foo3(CFoo("Bye world"));
        CFoo foo4 = CFoo("Bye again world");
        CFoo foo5 = foo4.ToUpper();
        CFoo foo6 = foo4.ToLower();

        foo6 = foo4.ToUpper();
        std::cout << "foo4: " <<  foo4.ToString() << std::endl;
        foo6 = CFoo("Well well well");
    }
    return 0;
}

如果代码不尽可能短,我很抱歉。但是只有几个要点可以看,即我努力在main()中调用move构造函数和在类Foo中定义各种构造函数。

我知道编译器设置允许关闭RVO和东西但是为了使用功能&#34;移动构造函数&#34;在性能感知代码中,应该有一个关于何时被调用的经典示例。如果情况并非如此,我可能会决定不使用移动构造函数。

要回答这个问题,你可以告诉我一行我可以在main()中编写,它可以调用CFoo的移动构造函数。或者你可以告诉我我做错了什么 std :: string是否支持这样移动?也许这就是为什么我的努力失败了?

提前谢谢。

2 个答案:

答案 0 :(得分:8)

在您尝试使用移动构造函数的所有尝试中,它都是elided,因此,例如CFoo foo = CFoo(blah);简单地等同于CFoo foo(blah);,它不需要使用移动构造函数。这是一个 Good Thing ,因为编译器正在优化对任何副本或移动的需求。

要查看正在使用的移动构造函数,请尝试:

CFoo f1;
CFoo f2 = std::move(f1);

这从rvalue构造f2,没有任何东西可以省略,因此将使用移动构造函数。

答案 1 :(得分:1)

首先,std::string ToUpper(const std::string& s)中存在错误,即result中没有空格。 C ++算法不会自动增长其目标容器。您必须自己分配空间,或使用插入器适配器。

为了腾出空间,例如这样做:

result.resize(s.length());

之后移动赋值运算符调用:

  • foo6 = foo4.ToUpper();
  • foo6 = CFoo("Well well well");

只要从相同类型的xvalue初始化对象,就会调用移动构造函数,其中包括:

  • 初始化,T a = std::move(b);T a(std::move(b));,其中b的类型为T
  • 函数参数传递:f(std::move(a));,其中a的类型为Tfvoid f(T t)
  • 函数返回:return a;位于T f()之类的函数中,其中a的类型为T,其中包含移动构造函数。

有关详情,请参阅cppreference.com上的move constructors