gpt4 book ai didi

c++ - 用于临时延长生命周期的 const 引用

转载 作者:太空狗 更新时间:2023-10-29 21:08:01 26 4
gpt4 key购买 nike

我对某些 C++ 标准合规性或不合规性有疑问。

在我的项目中,我使用了一些使用 const 引用技巧的简单 Guard 类。我使用的是 Visual Studio 2005,有两种配置 - 一种用于正常发布构建,另一种用于单元测试。

在这两种情况下,const 引用最后都会有一些临时挂起,但同时发生的事情才是问题所在。对于发布配置,const 引用直接指向在创建 Guard 实例的辅助函数模板的返回中创建的 temp(没有调用复制构造函数,甚至没有为此实例化)。

但是对于单元测试 conf,函数模板 temp 首先被复制,然后它的析构函数被调用,只有在 const 引用超出范围后才应该做的事情。

我已经通过禁用基类复制构造函数中的原始守卫解决了这个问题(因此不会为调用复制构造函数的配置触发析构函数中的操作),但困扰我的是:

复制临时行为是否符合标准?标准是否说明 const 引用应直接指向 temp,还是标准中未指定此实现定义的行为?

我的代码大致基于 DDJ 中的 Scope Guard 文章和 Herb Sutter 的 gotw 88 文章,但这两个来源似乎都没有考虑早期的析构函数调用。

任何来自更有知识的人的信息将不胜感激。

编辑:

好的代码是这样的:

class GuardBase
{
public:

GuardBase() : m_enabled(true)
{}

//this is done because in normal build no copy constructor is called ( directly using the function temporary)
//but for UT conf somehow the original temp is copied and destroyed
GuardBase(const GuardBase& other)
{
other.disable();
}

void disable() const
{
m_enabled = false;
}

protected:
//member is mutable because we will access the object through the const reference
mutable bool m_enabled;
};

template< typename Arg, typename ObjType, typename MemberMethod >
class Guard1Arg : public GuardBase
{
public:
Guard1Arg(ObjType& obj, MemberMethod remover, Arg arg) : m_arg(arg), m_remover(remover), m_object(obj)
{}

~Guard1Arg()
{
if ( m_enabled )
{
(m_object.*m_remover)(m_arg);
}
}

private:
Arg m_arg;
MemberMethod m_remover;
ObjType& m_object;

//this class should not be assigned
Guard1Arg& operator=(const Guard1Arg& other);

};

//utility template function used to create Guards using member functions with 1 argument
template<typename MemberFunction, typename Obj, typename Arg>
Guard1Arg<Arg, Obj, MemberFunction> MakeGuard1Arg(Obj& obj, MemberFunction memberFunction, Arg& arg)
{
return Guard1Arg<Arg, Obj, MemberFunction>(obj, memberFunction, arg);
}


#define GUARD_CREATE(arg, remover) const GuardBase& guard = MakeGuard1Arg(*this, remover, arg);
#define GUARD_DISABLE guard.disable();
#define GUARD_FRIEND template< typename Arg, typename ObjType, typename MemberMethod > friend class Guard1Arg;

最佳答案

这两种行为都符合标准。如果您有这样的代码:

T foo()
{
return T();
}

int main()
{
const T& x = foo();
}

然后,从概念上讲,在 foo 中,创建了一个临时对象。这个临时文件被复制到 foo 的返回值中。在 main 中,这个拷贝(也是一个临时对象)绑定(bind)到 x
作为 foo 的返回值的拷贝的生命周期得到延长,但作为拷贝源的临时文件却没有。

但是,C++ 标准明确允许省略多余的临时对象。因此,foo 可以直接在该槽中创建临时对象,而不是创建一个临时对象并将其复制到插槽中以获取返回值。
这两个选项都是可能的,编译器甚至不需要记录它何时使用哪个选项。

C++ 标准的相关部分是 6.6.3 ([stmt.return]) 和 12.2 ([class.temporary])。

关于c++ - 用于临时延长生命周期的 const 引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4086508/

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