[英]Why is the return value incorrect with optimisation flags on?
我(仅供我自己)练习 c++ 并尝试将 c# 属性“重新编码”到其中。 我知道它没用(我的意思是,我不会使用它)但是,我只是想看看这是否可能。
由于某些原因,使用以下代码,在最新的 clang / gcc 版本下,它不会在除-O0
之外的每个优化标志下产生正确的结果(据我所知,这会禁用优化。)
#include <functional>
#include <iostream>
template<typename T>
class Property
{
private:
using getType = std::function<const T&(void)>;
using setType = std::function<void(const T&)>;
T internal;
getType get;
setType set;
public:
Property(const T &value) : internal{value}, get{[this] () { return internal; }}, set{[this](const T& value) { internal = value; }} {}
Property(getType fnc) : get(fnc) { }
Property(getType fncGet, setType fncSet) : get(fncGet), set(fncSet) { }
Property(setType fnc) : set(fnc) { }
Property(setType fncSet, getType fncGet) : get(fncGet), set(fncSet) { }
Property<T> &operator=(T& value) { set(value); return *this; }
operator const T&() const { return get(); }
};
int main(void)
{
Property<int> hey(12);
std::cout << hey << std::endl;
return hey;
}
它似乎在 Visual Studio 编译器下表现正确,但我不确定。
我错过了标准的一部分吗? 我的代码不正确吗? clang / gcc / STL 中是否有错误?
我将我的代码放在名为 Godbolt 的网站上,以便在编译器之间轻松切换,我得到了同样不连贯的结果。
这是它为 c++14 / clang 14 打印的内容:
ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 0
624203080
最后一个数字在运行之间发生变化,但不是第一个让我认为它只需要未初始化的数据。
你的问题是这部分: using getType = std::function<const T&(void)>;
结合get{[this] () { return internal; }}
get{[this] () { return internal; }}
。
lambda 在这里不返回internal
作为引用,因此返回了internal
的副本,并且 - 在这里我不知道std::function
是如何实现的 - std::function
必须保存internal
的副本但返回它作为对那个比悬空的副本的引用。
将其更改为get{[this] () -> T& { return internal; }}
get{[this] () -> T& { return internal; }}
似乎解决了这个问题。
您初始化的 lambda 按get
返回,而不是按引用返回,这意味着返回的int
不再存在于std::function
机器中的某个位置。
您可以指定参考返回
[this] () -> const T& { return internal; }
注意,您应该使Property
不可复制且不可移动,因为在复制或移动时,您无法在std::function
成员中重新指向this
捕获。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.