gpt4 book ai didi

c++ - 依赖确定性破坏,避免返回破坏

转载 作者:搜寻专家 更新时间:2023-10-31 02:10:26 25 4
gpt4 key购买 nike

我一直在尝试修改我的日志记录类。但是,我遇到了一个问题。
我想把这个接口(interface)暴露给用户:

mylog() << "hello";

这个想法是mylogLogger的一个实例,它为定义的日志类型定义了一些有用的特性。它的 operator() 函数将返回类型为 LogStream 的实例。但是,我想在最后自动输出换行符,所以我想到了在 LogStream 的析构函数中这样做。

我当前的实现看起来像这样(LogStreamLogger 在很大程度上被简化了):

#include <iostream>

struct LogStream
{
~LogStream() { std::cout << '\n'; }

template<class T>
LogStream& operator<<(const T& t)
{
std::cout << t;
return *this;
}
};

struct Logger
{
LogStream operator()()
{
return LogStream{} << "message: ";
}
};

int main()
{
Logger log;
log() << "hello!";
}

有趣的是,我通过这段代码发现我之前的实现依赖于 RVO。编译器总是执行复制省略,所以析构函数确实按照我想要的方式运行。但是,对于这段代码,换行符被打印了两次,因为当复制发生在 operator() 中时,复制构造函数被调用。
当我不返回临时实例,而是将其放入 operator() 的正文中时,问题就消失了:

LogStream stream;
stream << "message: ";
return stream;

现在 RVO 让它按照我想要的方式工作。
我稍后在 = delete 上复制构造函数,因为无论如何它更有意义,这有效地导致代码无法编译。

我有什么选择来提供我想要的界面,而不使用依赖 RVO 的 hacky 解决方案?

最佳答案

LogStream 添加一个构造函数,它接受一个 char const *

LogStream(char const* c) { std::cout << c; }

然后,不是在 operator() 中创建一个临时的 LogStream,而是使用列表初始化来初始化返回值本身。

LogStream operator()()
{
return {"message: "};
}

因此避免了临时的和额外的新行。

Live demo (请注意,即使使用 -fno-elide-constructors 禁用复制省略也不会导致额外的换行符)。

关于c++ - 依赖确定性破坏,避免返回破坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45254710/

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