C++ 中的智能引用

zou*_*nds 4 c++ reference smart-pointers

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

是否可以在 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我不能使用它,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
Run Code Online (Sandbox Code Playgroud)

我可以使用右值引用使其与 STL 配合良好,

int_ref & operator=(int_ref && other){
    reseat(other);
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

但是返回 an 的函数int_ref将使用右值重载,我会得到以下结果:

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
Run Code Online (Sandbox Code Playgroud)

有没有解决的办法?总的来说,这是一个糟糕的主意吗?

Ste*_*sop 5

尝试这样做的一个问题是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&。这意味着您将获得引用语义的部分版本,这可能会以其自身的方式令人困惑。