gpt4 book ai didi

C++:我的右值在哪里?

转载 作者:太空宇宙 更新时间:2023-11-04 15:36:02 25 4
gpt4 key购买 nike

请考虑以下代码:

#include <iostream>

template <class T>
class value_wrapper
{
public:

value_wrapper(T& pv) : v(pv) { std::cout<< "CONS.REF:" << pv << " AT:" << (void*)this << std::endl; }
value_wrapper(T&& pv) : v(pv) { std::cout<< "CONS.UNIREF:" << pv << " AT:" << (void*)this << std::endl; }
virtual ~value_wrapper() { std::cout<< "DEST:" << v << " AT:" << (void*)this << std::endl; }
value_wrapper(const value_wrapper& ov) : v(ov.v) { std::cout<< "CONS.COPY.REF:" << v << " AT:" << (void*)this << std::endl; }
value_wrapper(value_wrapper&& ov) : v(ov.v) { std::cout<< "CONS.COPY.UNIREF:" << v << " AT:" << (void*)this << std::endl; }
value_wrapper<T>& operator = (value_wrapper<T>&& ov)
{
std::cout<< "ASSI.UNIREF: OF " << v << " AT:" << (void*)this << " TO:" << ov.v << " AT:" <<(void*)&ov << " ADR.VAL:" << (void*)(&ov.v)<< std::endl;
v = ov.v;
return *this;
}

private:
template <typename V> friend value_wrapper<V> operator - (const value_wrapper<V> v1, const V& v2);
T& v;
};

template<typename T>
value_wrapper<T> operator - (const value_wrapper<T> v1, const T& v2)
{
T f = v1.v - v2;
value_wrapper<T> res(f);
std::cout << "MINUS: RESULT:" << res.v << " AT:" << (void*)&res << " ADR.VAL:" << &res.v << std::endl;
return res;
}


template<typename X>
value_wrapper<X> _ (X& a)
{
return value_wrapper<X>(a);
}

int main()
{
int a = 5;

std::cout << "BEFOR:" << a<< std::endl;

_(a) = _(a) - 1;

std::cout << "AFTER:" << a<< std::endl;

return 0;

}

以及他们的在线形象:

(坏的)http://cpp.sh/7yav

(好的)http://coliru.stacked-crooked.com/a/ea7363eaba68a336

第一个输出:

BEFOR:5
CONS.REF:5 AT:0x761cebd52310
CONS.REF:4 AT:0x761cebd52320
MINUS: RESULT:4 AT:0x761cebd52320 ADR.VAL:0x761cebd522cc
CONS.REF:5 AT:0x761cebd52300
ASSI.UNIREF: OF 5 AT:0x761cebd52300 TO:0 AT:0x761cebd52320 ADR.VAL:0x761cebd522cc
DEST:0 AT:0x761cebd52300
DEST:27644 AT:0x761cebd52320
DEST:0 AT:0x761cebd52310
AFTER:0

第二个输出:

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
BEFOR:5
CONS.REF:5 AT:0x7fffc51a5710
CONS.REF:4 AT:0x7fffc51a5720
MINUS: RESULT:4 AT:0x7fffc51a5720 ADR.VAL:0x7fffc51a56fc
CONS.REF:5 AT:0x7fffc51a5700
ASSI.UNIREF: OF 5 AT:0x7fffc51a5700 TO:4 AT:0x7fffc51a5720 ADR.VAL:0x7fffc51a56fc
DEST:4 AT:0x7fffc51a5700
DEST:4 AT:0x7fffc51a5720
DEST:4 AT:0x7fffc51a5710
AFTER:4

那么,问题来了:

从右值具有正确值的那一刻起,它发生了什么:

减:结果:4 AT:0x761cebd52320 ADR.VAL:0x761cebd522cc

直到正确的值从同一个地址消失:

ASSI.UNIREF:OF 5 AT:0x761cebd52300 TO:0 AT:0x761cebd52320 ADR.VAL:0x761cebd522cc

看来,我使用与 cpp.sh 相同的编译器 (g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4),因为我得到相同的结果...

这是编译器错误,还是我对标准右值的工作方式有误解?

编辑:

我期望的行:

ASSI.UNIREF:OF 5 AT:0x761cebd52300 TO:0 AT:0x761cebd52320 ADR.VAL:0x761cebd522cc

成为:

ASSI.UNIREF:OF 5 AT:0x761cebd52300 TO:4 AT:0x761cebd52320 ADR.VAL:0x761cebd522cc

即:值 0 就像在其他打印输出中一样是 4,因为它必须是正确的值,而不是 0。

最佳答案

我认为你在这里有一个未定义的行为:

template<typename T>
value_wrapper<T> operator - (const value_wrapper<T> v1, const T& v2)
{
T f = v1.v - v2;
value_wrapper<T> res(f);
return res;
}

看到了吗?您返回的是 value_wrapper<T>封装了对 T 的引用,该引用指的是 f .缓冲区f是一个局部变量,所以你返回一个悬空引用,也就是UB。

关于C++:我的右值在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33625525/

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