【问题标题】:Niether Copy nor Move constructor called in c++在 C++ 中调用的 Copy 和 Move 构造函数均未调用
【发布时间】:2013-12-18 04:22:25
【问题描述】:

我有以下课程可供测试!

class ArrayClass
{
private:
    int isize;
    double* p ;
public:
    ArrayClass(int num_ =1):isize(num_),p(new double[num_])
    {
        cout << "constructor with num!!" << endl ;
        for(int idx=0;idx<num_;idx++)
        {
            p[idx] = 0.0 ;
        }
    }
    ArrayClass(const ArrayClass& m) //copy constructor
    {
        cout << "copy constructor!!" << endl ;
        isize = m.getsize() ;
        p = new double[isize] ;
        std::copy(m.getaddr(), m.getaddr() + m.getsize(), p);
    }
    ArrayClass& operator=(const ArrayClass& m) //copy assignment
    {
        cout << "copy assignment!!" << endl ;
        if(this != &m)
        {
            int msize =  m.getsize() ;
            if(isize != msize )
            {
                delete []p ;
                p = 0x00 ;
                p = msize ? new double[msize] : 0x00 ;
                isize = msize ;
            }
            std::copy(m.getaddr(), m.getaddr() + msize, p);
        }
        return *this ;
    }
    ArrayClass& operator=(ArrayClass&& m)
    {
        cout << "Move assignment!!" << endl ;
        isize = m.getsize() ;
        p = m.getaddr() ;
        m.initialize() ;
        return *this ;
    }
    ArrayClass(ArrayClass&& m)
    {
        cout << "Move Constructor!!" << endl ;
        isize = m.getsize() ;
        p = m.getaddr() ;
        m.initialize() ;
    }
    ~ArrayClass()
    {
        cout << "desctrutor!!" << endl ;
        delete []p ;
    }
    void initialize(){ isize=0; p=0x00; }
    int  getsize() const { return isize; }
    double* getaddr() const { return p; }
    double& operator[](int i)
    {
        if( i >= isize)
            throw "the bound is wrong!!" ;
        return p[i] ;
    }
    const double& operator[](int i) const
    {
        if( i >= isize)
            throw "the bound is wrong!!" ;
        return p[i] ;
    }
    void Print(void)
    {
        for(int idx=0;idx<isize;idx++)
            cout << p[idx] << " " ;
        cout << endl ;
    }
} ;

ArrayClass  func()
{
    ArrayClass m(10) ;
    for(int idx=0;idx<10;idx++)
        m[idx] = idx * idx + 1 ;
    return m ;
}

使用 g++ --std=c++0x x.cpp -o x.exe 在 RedHat Linux 中以 g++ 4.4.6 编译

以下是我所期望的:

ArrayClass m2(std::move(func())) ;
m2.Print() ;

输出:

constructor with num!!
Move Constructor!!
desctrutor!!
1 2 5 10 17 26 37 50 65 82
desctrutor!!

但以下不是我所期望的:

ArrayClass m2(func()) ;
m2.Print() ;

输出:

constructor with num!!
1 2 5 10 17 26 37 50 65 82
desctrutor!!

我希望应该有“复制构造函数!!” ,我很好奇,这次测试没有调用拷贝构造函数,也没有调用移动构造函数,怎么m2.Print()的答案是对的?!

【问题讨论】:

  • 每天有多少复制/移动省略问题?
  • 而且你应该在传递prvalue时期望移动构造。
  • 如果使用 GCC 选项 -fno-elide-constructors 编译会发生什么?那应该会给你答案。
  • 在您了解问题所在之后,要带回家的教训是不要帮助编译器。让它发挥它的魔力,当编译器可以很好地忽略整个操作时不要强行移动!
  • @David,谢谢,复制省略真的对我有很大帮助!

标签: c++ class c++11 constructor


【解决方案1】:

这称为复制省略(尽管您在这里基本上省略了移动操作)。如果语义保持不变,您可以就地构造对象。

【讨论】:

  • 技术上它仍然被称为复制省略,即使省略的操作是移动。 12.8/31 [...]这种复制/移动操作的省略,称为复制省略[...]
  • definedbehavior.blogspot.tw/2011/08/…这个网页真的解释了复制省略很多!干得好!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
  • 2017-09-13
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 2015-03-17
  • 1970-01-01
相关资源
最近更新 更多