C++ 具有引用成员的赋值运算符
这是创建具有引用成员的赋值运算符的有效方法吗C++ 具有引用成员的赋值运算符,c++,reference,C++,Reference,这是创建具有引用成员的赋值运算符的有效方法吗 #include <new> struct A { int &ref; A(int &Ref) : ref(Ref) { } A(const A &second) : ref(second.ref) { } A &operator =(const A &second) { if(this == &second)
#include <new>
struct A
{
int &ref;
A(int &Ref) : ref(Ref) { }
A(const A &second) : ref(second.ref) { }
A &operator =(const A &second)
{
if(this == &second)
return *this;
this->~A();
new(this) A(second);
return *this;
}
}
#包括
结构A
{
int&ref;
A(int&Ref):Ref(Ref){}
A(常数A&second):ref(second.ref){}
运算符=(常量A和秒)
{
如果(此==&秒)
归还*这个;
这个->~A();
新(本)A(第二);
归还*这个;
}
}
< >似乎编译得很好,但是C++在没有预料到的情况下倾向于不确定的行为,所有那些说不可能的人,我想我错过了一些机会。我错过了什么吗?据我所知,你所做的技术上是正确的,但会带来麻烦。例如,考虑派生类从<代码> A<代码>中发生的情况,因为它的赋值操作符生成新对象(切片)。你不能在你的类中将引用变成指针吗
除此之外,复制构造函数和赋值运算符通常通过
const&
获取其参数。您所做的是正确的,但这并不是编写复制赋值运算符的非常安全的方法。此外,您应该考虑使用指针成员而不是引用成员。
您应该使用实现它。与您的实现相比,它至少有3个优点。它在语法上是正确的。但是,如果新位置抛出,则 最终得到一个你无法破坏的对象。更不用说灾难了 如果有人来自你的班级。不要这样做 解决方案很简单:如果类需要支持赋值,则不要 使用任何参考成员。我有很多课程可以参考 参数,但将它们存储为指针,这样类就可以支持 分配比如:
struct A
{
int* myRef;
A( int& ref ) : myRef( &ref ) {}
// ...
};
另一种解决方案是使用reference_包装类(在函数头中): 结构A { A(int&A):A_uz(A){} A(常数A&A):A(A.A){ A&A运算符=(常量A&A) { a=a.a; 归还*这个; } void公司()常数 { ++a); } 标准::参考包装; };
顺便说一下,
运算符=
和复制构造函数的参数应该是常量引用。正确性可能仅限于标准布局类型,由于使用virtuals时,此
不必是指向内存块开头的指针。如果需要这样做,我建议重新考虑使用引用。引用无法重置。如果你需要重新安装一个,那么引用一开始就不是正确的类型。这怎么会产生问题呢?但是如何交换引用呢?@ChristianRau:无论如何,你将实现自己的交换函数。是的,这可能需要交换引用。具体来说,swap
需要销毁A
,然后调用placement new,就像这样。复制和交换取决于是否有可用的nothrow交换实现,而这种类型没有。@DennisZickefoose:它可以为您节省自分配检查。我喜欢这样——简单明了的解决方案!使用赋值表达式a=b代码>当a
具有类型reference\u wrapper
时,似乎如果b
具有类型(可转换为?reference\u wrapper
),这将重置a
以引用b
,但如果没有,并且b
具有类型(可转换为?T
,a
引用的T
对象将被分配值b
。这是真的吗?如果是这样的话,它似乎为实现执行a=b的函数模板引入了一些微妙之处我们不知道具体的类型,但只有b
的类型可以隐式转换为a
。
struct A
{
A(int& a) : a_(a) {}
A(const A& a) : a_(a.a_) {}
A& operator=(const A& a)
{
a_ = a.a_;
return *this;
}
void inc() const
{
++a_;
}
std::reference_wrapper<int>a_;
};