首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在c++11中,是否仍然需要传入对将接受函数输出的对象的引用?

在c++11中,是否仍然需要传入对将接受函数输出的对象的引用?
EN

Stack Overflow用户
提问于 2012-06-16 12:54:18
回答 3查看 235关注 0票数 5

在C++11之前,如果我有一个在大型对象上操作的函数,我的直觉是用这种原型编写函数。

代码语言:javascript
复制
void f(A &return_value, A const &parameter_value);

(在这里,return_value只是一个空白对象,它将接收函数的输出。A只是一个很大且复制成本很高的类。)

在C++11中,利用移动语义,默认建议(据我所知)是更直接的:

代码语言:javascript
复制
A f(A const &parameter_value);

还需要用旧的方法,传入一个对象来保存返回值吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-06-16 21:19:02

其他人则介绍了A可能没有廉价的move构造函数的情况。我猜你的A是这样的。但还有一种情况下,您可能需要传入一个"out“参数:

如果A是像vectorstring这样的类型,并且已知"out“参数已经具有可以在f中重用的资源(例如内存),那么如果可以的话,重用该资源是有意义的。例如,考虑以下内容:

代码语言:javascript
复制
void get_info(std::string&);
bool process_info(const std::string&);

void
foo()
{
    std::string info;
    for (bool not_done = true; not_done;)
    {
        info.clear();
        get_info(info);
        not_done = process_info(info);
    }
}

vs:

代码语言:javascript
复制
std::string get_info();
bool process_info(const std::string&);

void
foo()
{
    for (bool not_done = true; not_done;)
    {
        std::string info = get_info();
        not_done = process_info(info);
    }
}

在第一种情况下,随着循环的执行,容量将在string中建立,然后在循环的每次迭代中潜在地重用该容量。在第二种情况下,每次迭代都会分配一个新的string (忽略小字符串优化缓冲区)。

这并不是说您永远不应该按值返回std::string。只是你应该意识到这个问题,并在个案的基础上应用工程判断。

票数 7
EN

Stack Overflow用户

发布于 2012-06-16 13:00:46

对象可能很大,并且复制成本很高,并且对于这种情况,移动语义不能通过复制来改进。考虑一下:

代码语言:javascript
复制
struct A {
    std::array<double,100000> m_data;
};

以这种方式设计对象可能不是一个好主意,但如果出于某种原因,您有一个这种类型的对象,并且您想要编写一个函数来填充数据,那么您可以使用out参数。

票数 3
EN

Stack Overflow用户

发布于 2012-06-16 13:09:40

这取决于:您的编译器是否支持返回值优化,以及您的函数f是否设计为能够使用您的编译器支持的RVO?

如果是这样,那么是的,一定要通过值返回。通过传递可变参数,您将一无所获,并且通过这种方式,您将获得大量的代码清晰度。如果不是,那么您必须研究A的定义。

对于某些类型,移动只不过是复制而已。如果A不包含任何实际值得移动的东西(指针、所有权转移等等),那么您不会从移动中获得任何好处。毕竟,移动不是免费的;它只是一个副本,它知道原来拥有的任何东西都被转移到了副本上。如果类型不拥有任何东西,那么移动只是一个副本。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11060928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档