2
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <memory>

using std::cout;
using std::vector;


class Has_ptr {
public:
    friend void swap(Has_ptr &lhs, Has_ptr &rhs);
    friend bool operator<(const Has_ptr &a, const Has_ptr &b);

    
    // constructor
    Has_ptr(const std::string &s, int num) : ptr(new std::string(s)), i(num) {}

    // copy constructor
    Has_ptr(const Has_ptr &a) : ptr(new std::string(*a.ptr)), i(a.i) {}


    // copy-assign operator
    /*
    Has_ptr& operator=(Has_ptr tmp) 
    {
        this->swap(tmp);
        return *this;
    }
    */

    /*
    Has_ptr& operator=(Has_ptr &tmp) 
    {
        std::string *x = new std::string(*(tmp.ptr));
        delete ptr;
        ptr = x;
        i = tmp.i;
        return *this;
    }
    */

    

    // destructor
    ~Has_ptr() {
        delete ptr;
    }
    
    void swap(Has_ptr &rhs) {
        using std::swap;
        swap(ptr, rhs.ptr);
        swap(i, rhs.i);
    }
    
    void print() {
        cout << *ptr << i;
    }
private:
    std::string *ptr;
    int i;
};


// add a swap function
void swap(Has_ptr &lhs, Has_ptr &rhs) {
    lhs.swap(rhs);
}


bool operator<(const Has_ptr &a, const Has_ptr &b) {
    return a.i < b.i;
}

在 C++ Primer 5th,13.3 Swap 中,练习 13.31。问题需要给类Has_ptr一个 < 运算符并创建一个元素很少的向量,然后对向量进行排序。类的实现如上。

Has_ptr有 2 个数据成员

  1. 字符串指针ptr,指向动态内存
  2. 诠释我

Has_pt r 类具有以下复制控制成员

  1. 构造函数接受一个字符串和一个 int。
  2. copy_constructor,实现为类行为像值。
  3. 删除由ptr分配的动态内存的析构函数。

我为复制分配运算符尝试了两种实现。一个我首先创建临时字符串指针变量 x 来保存 RHS 指针,然后删除 LHS 指针,最后将 RHS 分配给 LHS。但是,这种实现使代码无法编译。

Has_ptr& operator=(Has_ptr &tmp) 
{
    std::string *x = new std::string(*(tmp.ptr));
    delete ptr;
    ptr = x;
    i = tmp.i;
    return *this;
}

第二种实现使用了复制和交换。这使得代码编译并碎片化运行。

// copy and swap
Has_ptr& operator=(Has_ptr tmp) 
{
    this->swap(tmp);
    return *this;
}

我的主要功能如下

int main() {
    Has_ptr a("a", 0), b("b", 1), c("c", 2);
    a.print();
    vector<Has_ptr> coll{a, b, c};

    std::sort(coll.begin(), coll.end());

    for (auto h : coll) 
        h.print();
}

第二种实现在编译器时不产生错误/警告消息并产生以下输出

a0a0

第一个实现产生以下错误消息

In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\algorithm:62:0,             

    from 13_31.c++:9:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h: In instantiation of 'void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]':
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1882:25:   required from 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1968:31:   required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:4707:18:   required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >]'
13_31.c++:88:39:   required from here
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1849:17: error: invalid initialization of non-const reference of type 'Has_ptr&' from an rvalue of type 'std::remove_reference<Has_ptr&>::type {aka Has_ptr}'
        *__first = _GLIBCXX_MOVE(__val);
                 ^
13_31.c++:42:14: note:   initializing argument 1 of 'Has_ptr& Has_ptr::operator=(Has_ptr&)'
     Has_ptr& operator=(Has_ptr &tmp)
              ^~~~~~~~
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:61:0,
                 from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\algorithm:62,
                 from 13_31.c++:9:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_heap.h: In instantiation of 'void std::__pop_heap(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]':
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1672:19:   required from 'void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1930:25:   required from 'void std::__partial_sort(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1945:27:   required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Size = int; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1965:25:   required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:4707:18:   required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >]'
13_31.c++:88:39:   required from here
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_heap.h:246:17: error: invalid initialization of non-const reference of type 'Has_ptr&' from an rvalue of type 'std::remove_reference<Has_ptr&>::type {aka Has_ptr}'
       *__result = _GLIBCXX_MOVE(*__first);
                 ^
13_31.c++:42:14: note:   initializing argument 1 of 'Has_ptr& Has_ptr::operator=(Has_ptr&)'
     Has_ptr& operator=(Has_ptr &tmp)
              ^~~~~~~~
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:61:0,
                 from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\algorithm:62,
                 from 13_31.c++:9:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_heap.h: In instantiation of 'void std::__adjust_heap(_RandomAccessIterator, _Distance, _Distance, _Tp, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Distance = int; _Tp = Has_ptr; _Compare = __gnu_cxx::__ops::_Iter_less_iter]':
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_heap.h:335:22:   required from 'void std::__make_heap(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1669:23:   required from 'void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1930:25:   required from 'void std::__partial_sort(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1945:27:   required from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Size = int; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1965:25:   required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:4707:18:   required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >]'
13_31.c++:88:39:   required from here
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_heap.h:220:29: error: invalid initialization of non-const reference of type 'Has_ptr&' from an rvalue of type 'std::remove_reference<Has_ptr&>::type {aka Has_ptr}'  
    *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
                             ^
13_31.c++:42:14: note:   initializing argument 1 of 'Has_ptr& Has_ptr::operator=(Has_ptr&)'
     Has_ptr& operator=(Has_ptr &tmp)
              ^~~~~~~~
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:61:0,
                 from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\algorithm:62,
                 from 13_31.c++:9:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_heap.h:226:29: error: invalid initialization of non-const reference of type 'Has_ptr&' from an rvalue of type 'std::remove_reference<Has_ptr&>::type {aka Has_ptr}'
    *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
                             ^
13_31.c++:42:14: note:   initializing argument 1 of 'Has_ptr& Has_ptr::operator=(Has_ptr&)'
     Has_ptr& operator=(Has_ptr &tmp)
              ^~~~~~~~
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\char_traits.h:39:0,
                 from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\ios:40,
                 from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\ostream:38,
                 from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\iostream:39,
                 from 13_31.c++:6:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algobase.h: In instantiation of 'static _BI2 std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1 = Has_ptr*; _BI2 = Has_ptr*]':
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algobase.h:588:58:   required from '_BI2 std::__copy_move_backward_a(_BI1, _BI1, _BI2) [with bool _IsMove = true; _BI1 = Has_ptr*; _BI2 = Has_ptr*]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algobase.h:598:5:   required from '_BI2 std::__copy_move_backward_a2(_BI1, _BI1, _BI2) [with bool _IsMove = true; _BI1 = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _BI2 = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algobase.h:668:48:   required from '_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1 = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _BI2 = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1848:8:   required from 'void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1882:25:   required from 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:1968:31:   required from 'void std::__sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >; _Compare = __gnu_cxx::__ops::_Iter_less_iter]'
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algo.h:4707:18:   required from 'void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<Has_ptr*, std::vector<Has_ptr> >]'
13_31.c++:88:39:   required from here
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_algobase.h:548:18: error: invalid initialization of non-const reference of type 'Has_ptr&' from an rvalue of type 'std::remove_reference<Has_ptr&>::type {aka Has_ptr}'
      *--__result = std::move(*--__last);
      ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
13_31.c++:42:14: note:   initializing argument 1 of 'Has_ptr& Has_ptr::operator=(Has_ptr&)'
     Has_ptr& operator=(Has_ptr &tmp)
              ^~~~~~~~
4

0 回答 0