gpt4 book ai didi

c++ - C++ 中的简单存储类和严格的别名

转载 作者:搜寻专家 更新时间:2023-10-31 01:58:22 24 4
gpt4 key购买 nike

我有以下代码用于存储一个小类。

#include <iostream>

template<typename T>
class storage
{
private:
struct destroy
{
T& m_t;
destroy(T& t) : m_t(t) { }
~destroy() { m_t.~T(); }
};

char m_c[sizeof(T)];
void* address() { return &m_c[0]; }

public:
void set(const T& t) { new (address()) T(t); }

T get()
{
T& t = *static_cast<T*>(address());
destroy _d(t);
return t;
}

};

template<typename T>
class choosable_storage
{
private:
union
{
T* m_p;
storage<T> m_storage;
};
bool m_direct;

public:
choosable_storage() : m_direct(false) { }

void set_direct(const T& t)
{
m_direct = true;
m_storage.set(t);
}

void set_indirect(T* const t) { m_p = t; }

T get()
{
if (m_direct) return m_storage.get();
return *m_p;
}

};

int main(void)
{
storage<int> s; // no problems
s.set(42);
std::cout << s.get() << std::endl;

int i = 10;

choosable_storage<int> c1; // strict aliasing warnings
c1.set_indirect(&i);
std::cout << c1.get() << std::endl;

choosable_storage<int> c2;
c2.set_direct(i);
std::cout << c2.get() << std::endl;

return 0;
}

gcc 4.4 警告我在返回时违反了 storage::get() 中严格的别名规则。

据我所知,我没有违反任何规则。我真的违反了严格的别名还是 gcc 在这里变得挑剔?

有没有办法在不禁用严格别名的情况下让它不发出警告?

谢谢

编辑:

另一方面,下面的实现不会给出任何警告:

template<typename T>
class storage
{
private:
struct destroy
{
T& m_t;
destroy(T& t) : m_t(t) { }
~destroy() { m_t.~T(); }
T const& operator()() const { return m_t; }
};

char m_c[sizeof(T)];

public:
void set(const T& t) { new(static_cast<void*>(m_c)) T(t); }

T get(void) { return destroy(*static_cast<T*>(static_cast<void*>(m_c)))(); }

};

编辑:

gcc 4.5 及更高版本不会发出警告 - 所以显然这只是对严格别名规则的误解或 gcc 4.4.x 中的错误

最佳答案

Do I actually violate strict aliasing or is gcc getting picky here?

严格别名规则有两种不同的解释:

  • 通常的弱严格别名规则:(char/unsigned char 类型除外)您不能使用强制转换或 union 来执行类型双关,你需要memcpy(或两次volatile访问);这样的代码确实不太合理,并且在 C(除了最新的非常荒谬的 C 标准)和 C++ 中被明确禁止。
  • 不寻常的严格别名规则:您不能重用内存:一旦内存区域具有“动态类型”(什么?),它就不能与其他类型一起使用。所以你不能写一个分配器函数(malloc 替代)C,除非它每次只调用 malloc/free

强规则定义不明确,破坏了许多合理的代码,并且出于某种原因被 GCC 维护者选择(完全基于 self 欺骗和循环论证 - 这真的很丑陋)。为了使 C++ 代码与强大的严格别名优化一起工作,G++ 的维护者为典型的 C++ 代码添加了悲观(基于更多的 self 欺骗),以保持优化!

我不知道他们是否/何时意识到自己的错误,如有疑问,请禁用严格别名。无论如何,这是一个非常小的优化。

关于c++ - C++ 中的简单存储类和严格的别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4170146/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com