bkx*_*kxp 12 c++ swap reference unions
有时类会引用其他类.实现std::swap()这样的类不是直截了当的,因为它会导致原始实例而不是引用的交换.下面的代码说明了这种行为:
#include <iostream>
class A
{
int& r_;
public:
A(int& v) : r_(v) {}
void swap(A& a)
{
std::swap(r_, a.r_);
}
};
void test()
{
int x = 10;
int y = 20;
A a(x), b(y);
a.swap(b);
std::cout << "x=" << x << "\n"
<< "y=" << y << "\n";
}
int main()
{
test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
联合的简单解决方法:
class A
{
union
{
int& r_;
size_t t_;
};
public:
A(int& v) : r_(v) {}
void swap(A& a)
{
std::swap(t_, a.t_);
}
};
Run Code Online (Sandbox Code Playgroud)
这很有效,但并不帅.有没有更好的方法来交换C++中的两个引用?另外,C++标准如何解释在一个联合中混合引用和值,考虑到在Stroustrup的"The C++ Programming Language"一书中,"引用"被定义为"对象的替代名称,别名"(p.189).
Rei*_*ica 22
你正在使用的联合技巧就像代码获取一样不可移植.该标准对编译器如何实现引用没有任何要求.他们可以(并且很可能)使用引擎盖下的指针,但这绝不保证.且不说事实sizeof(size_t)和sizeof(T*)不等于总是需要的.
您的问题的最佳答案是:如果您需要可分配/可交换的类,请不要使用引用成员.只需使用指针成员即可.毕竟,根据定义,引用是不可重载的,但是由于希望类可交换,您需要一些可重命名的东西.这是一个指针.
您可以使用std::reference_wrapper而不是直接引用(您不能swap)或指针(可能是nullptr).就像是:
class A
{
std::reference_wrapper<int> r;
public:
A(int& v) : r(v) {}
void swap(A& rhs)
{
std::swap(r, rhs.r);
}
int& get() const { return r; }
};
Run Code Online (Sandbox Code Playgroud)
您使用的程序union不合法,因为您分配引用但交换整数而不是打算再次使用引用.您可以在这里阅读有关原因的信息:访问非活动的union成员和未定义的行为?
这里一个简单的解决方案是使用指针而不是引用.一切都会顺利进行,没有特殊的代码.如果你真的不喜欢这个,也许你可以使用boost::optional<int&>而不是简单的引用,但我很难看到它会如何变得更好.
| 归档时间: |
|
| 查看次数: |
3767 次 |
| 最近记录: |