首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么基类数据成员的这种访问被认为是类型双关(在优化的构建中)?

为什么基类数据成员的这种访问被认为是类型双关(在优化的构建中)?
EN

Stack Overflow用户
提问于 2021-07-10 09:32:52
回答 1查看 67关注 0票数 0

我发现了一些类似于:

代码语言:javascript
复制
#include <utility>
#include <cstdlib>

struct Core
{
  void* mData{};
  size_t mCount{};
};

template <typename T>
struct Actual: protected Core
{
  Actual() = default;

  Actual(Actual<T> const& other) = delete;
  Actual<T>& operator=(Actual<T> const& other) = delete;

  Actual(Actual<T>&& other):
    Core{ other.mData, other.mCount }
  {
    other.mData = nullptr;
    other.mCount = 0;
  }

  Actual<T>& operator=(Actual<T>&& other)
  {
    Actual<T> tmp(std::move(other));
    std::swap(mData, tmp.mData);    // with -O2 -Wall -Wextra -Werror: "error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]"
    mCount = tmp.mCount;            // ditto
    return *this;
  }      

  ~Actual() { /* delete[] mData as array of T, if it was created */ }

  // rest of the API incl. allocating that array of T into mData, not relevant
};

int main() {
  Actual<int> a;
  Actual<int> b;
  b = std::move(a);
}

在请求优化之前,这是很好的编译(-O2和更高版本)。

问题很简单,为什么编译器(GCC 9.3.0)认为这是类型双关/违反严格的混叠规则,我能做些什么来解决这个问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-10 09:54:20

看上去像GCC的虫子。GCC 9.4及更高版本不能诊断这一点。

如果您这样重写operator=,它就不再抱怨了,这个表单也更短了。

代码语言:javascript
复制
Actual<T>& operator=(Actual<T> other)
{
    std::swap(mData, other.mData);
    std::swap(mCount, other.mCount); // I like this more than `mCount = tmp.mCount;`.
    return *this;
}

要使其工作,您必须删除Actual<T>& operator=(Actual<T> const& other) = delete;,还不如删除Actual(Actual<T> const& other) = delete;

您还应该将noexcept添加到move构造函数和这个赋值操作符中,以免标准容器(当调整大小时)决定复制类的实例而不是移动它们。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68326497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档