c – 如何复制(或交换)包含引用或const的成员的类型的对象?

c – 如何复制(或交换)包含引用或const的成员的类型的对象?,第1张

概述我正在尝试解决的问题是产生容器,例如包含引用和const数据成员的对象的std ::向量: struct Foo;struct Bar { Bar (Foo & foo, int num) : foo_reference(foo), number(num) {}private: Foo & foo_reference; const int number; // Mutable 我正在尝试解决的问题是产生容器,例如包含引用和const数据成员的对象的std ::向量:
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的成员的类型的对象?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1253865.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存