struct Foo;struct bar { bar (Foo & foo,int num) : foo_reference(foo),number(num) {}private: Foo & foo_reference; const int number; // Mutable member data elIDed};struct Baz { std::vector<bar> bar_vector;};
这不会按原样工作,因为由于引用成员foo_reference和const成员编号,Foo类的默认赋值运算符无法构建.
一个解决方案是将foo_reference更改为指针,并摆脱const关键字.然而,这种引用超出了指针的优点,而且这个const成员真的应该是const.他们是私人会员,所以唯一可以伤害的是我自己的代码,但是我用脚本(或更高版本)用自己的代码开q.
我已经在网络上看到了解决这个问题的解决方案,其中swap方法看起来充满了基于reinterpret_cast和const_cast的奇迹的未定义的行为.发生这些技术似乎在我的电脑上工作.今天.具有一个特定编译器的特定版本.明天还是用不同的编译器?谁知道.我不会使用依赖于未定义行为的解决方案.
stackoverflow的相关答案:
> Does it make sense to implement the copy-assignment operator in a class with all const data members?
第一个答案有趣的线条:“如果那个是不可变的,你的螺丝”.
> Swap method with const members
第一个答案在这里并不真正适用,第二个是有点污泥.
那么有没有办法为这样的类写一个不调用未定义行为的交换方法/复制构造函数,或者我刚刚搞砸了?
编辑
为了说清楚,我已经很清楚这个解决方案:
struct bar { bar (Foo & foo,int num) : foo_ptr(&foo),number(num) {}private: Foo * foo_ptr; int number; // Mutable member data elIDed};
这显然消除了数字的常数,并消除了foo_reference的隐含常量.这不是我后来的解决方案.如果这是唯一的非UB解决方案,那就可以了.我也很清楚这个解决方案:
voID swap (bar & first,bar & second) { char temp[sizeof(bar)]; std::memcpy (temp,&first,sizeof(bar)); std::memcpy (&first,&second,sizeof(bar)); std::memcpy (&second,temp,sizeof(bar));}
然后使用copy-and-swap写入赋值运算符.这会绕过引用和const问题,但它是UB吗? (至少它不使用reinterpret_cast和const_cast.)一些可爱的可变数据是包含std :: vectors的对象,所以我不知道这样一个浅的副本是否会在这里工作.
解决方法 如果您使用移动运算符实现此 *** 作有一种方法:bar & bar :: operator = (bar && source) { this -> ~ bar (); new (this) bar (std :: move (source)); return *this;}
你不应该真正使用这个技巧与复制构造函数,因为它们可以经常抛出,然后这是不安全的.移动构造函数永远不会抛出,所以这应该是可以的.
std :: vector和其他容器现在在可能的情况下利用移动 *** 作,所以调整大小和排序等等都可以.
这种方法将允许您保留const和引用成员,但是您仍然无法复制对象.要做到这一点,你必须使用非const和指针成员.
顺便说一句,你不应该像非POD类型那样使用memcpy.
编辑
对未定义行为投诉的回应.
问题情况似乎是
struct X { const int & member; X & operator = (X &&) { ... as above ... } ...};X x;const int & foo = x.member;X = std :: move (some_other_X);// foo is no longer valID
如果您继续使用foo,那么它是未定义的行为.对我来说这是一样的
X * x = new X ();const int & foo = x.member;delete x;
其中很明显使用foo是无效的.
也许X :: operator =(X&&)的一个天真的阅读会导致你认为可能foo在移动后仍然有效,有点像这样
const int & (X::*ptr) = &X::member;X x;// x.*ptr is x.memberX = std :: move (some_other_X);// x.*ptr is STILL x.member
成员指针ptr在x的移动中幸存下来,但是foo没有.
总结以上是内存溢出为你收集整理的c – 如何复制(或交换)包含引用或const的成员的类型的对象?全部内容,希望文章能够帮你解决c – 如何复制(或交换)包含引用或const的成员的类型的对象?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)