C ++中的智能引用

时间:2011-09-17 19:36:56

标签: c++ reference smart-pointers

编辑:Welp,我想这是一个糟糕的主意。

是否可以使用与普通C ++引用相同的语义在C ++中创建一个智能引用(对于特定类,因为您不能重载。运算符),但是在STL容器中使用时会重新设置?

例如,如果我有一些int_ref类,正常的整数运算符被重载,构造和赋值看起来像这样:

class int_ref{
    int * p;
public:
    int_ref(int * ip) : p(ip) {}
    int_ref(const int_ref & other) : p(other.p) { 
        /* maybe some refcounting stuff here */ 
    }
    int_ref & operator = (const int_ref & other){
        if (!p) 
            throw something_bad();
        *p = *other.p;
        return *this;
    }
    void reseat(const int_ref & other){
        p = other.p;
    }
}

然后我不能在std::vector中使用它,因为它不会重置引用,我不想要这样的事情:

std::vector<int_ref> vec;
int_ref five = new int(5);
vec.push_back(five);
vec.push_back(new int(1));
std::sort(vec.begin(), vec.end()); // the value of five is now 1

我可以使用右值引用使它与STL一起发挥很好,

int_ref & operator=(int_ref && other){
    reseat(other);
    return *this;
}

但是返回int_ref的函数会使用rvalue重载,我会得到这个:

int_ref make_number(){
    return new int(10);
}

int_ref ref = new int(5);
int_ref other = ref;
other = make_number();    // instead of copying, as a reference would,
                          // other now points to something other than ref

有解决方法吗?这一般只是一个可怕的想法吗?

2 个答案:

答案 0 :(得分:4)

甚至尝试这样做的一个问题是operator&。作为参考,它为您提供了参考地址(因为参考没有地址)。但是,对于容器的元素,它应该为您提供元素的地址(因为它们具有地址)。

因此,容器的元素在这方面无法模仿引用语义。如果重载operator&以返回参与地址,则例如违反了vector的连续存储保证,因为它对所有&v[n] == &v[0] + n 0 <= n < v.size() > 发明了

boost::addressof()来解决这个问题,因此您不必使用&来获取通用代码中对象的地址。但即使是标准也懒得说static_cast<T*>(&static_cast<char&>(v[n]))而不是&v[n]。即使您正在考虑使用它,也很难确定何时需要对象的实际地址,以及何时需要对象作者认为您想要的地址。最好永远不要超过一元operator&。这意味着您将获得部分版本的引用语义,这可能会以自己的方式引起混淆。

答案 1 :(得分:3)

你可能想要使用的是一个提升:ptr_ {container}。

您将指针存储在容器中(并且容器具有所有权)。但是当访问对象时,您将获得对象的引用而不是指针。

#include <boost/ptr_container/ptr_vector.hpp>

int main()
{
     boost::ptr_vector<int>    data;
     data.push_back(new int(5));


     std::cout << data[0] << "\n";  // Prints 5 as you get a reference to the object.
}

或者,如果您只想要参考。然后你可以使用boost:ref