繁体   English   中英

用C ++返回对象

[英]Returning an object in C++

我是从C和Java为主的背景学习C ++的,我很好奇在没有复制对象的情况下以C ++返回对象的最佳方法是什么。 根据我的理解,C ++ 11引入了右值引用(&&),以从临时变量(反对复制)移动数据。 例:

std::string getStr(){
   return "Hello";
}

std::string &&hello = getStr();

我可以想到的另一种方法是使用共享指针。

std::tr1::shared_ptr<std::string> getStr(){

    std::tr1::shared_ptr<std::string> hello(new std::string("Hello"));
    return hello;

}

auto hello = getStr();

我想也许右值引用会更好,但是在使用它之前我想先征求第二意见。 哪个更好?

如果不使用构造函数设置它们,是否还建议将类中的字段作为右值引用? 例:

class StringHolder{

   public:
     std::string &&str;
};

StringHolder sh;
sh.str = getStr();

非常感谢你们!

这个问题可能会重复出现。 这是一个经常提出的问题。 但是我还是想回答。

在C ++ 11中,当您是std::string之类的对象的客户端时,应按值传递它,而不必太担心效率:

std::string getStr(){
   return "Hello";
}

std::string hello = getStr();

在此级别上,您无需关心右值引用。 只是知道std::string可以非常高效地从rvalues(例如getStr()的返回getStr() “复制”。 该“副本”实际上称为“移动”,由于您是从右值(匿名临时副本)进行复制而自动启用的。

不要尝试通过恢复引用计数来优化复制。 仅在需要共享所有权语义时才使用引用计数。 这个说法并不总是正确的。 但是对于学习基础知识来说,它非常接近,这是遵循的良好经验法则。

在设计需要按值传递的类时,您需要开始担心右值引用:

class Widget
{
    // pointer to heap data
public:
    // ...
};

为了简要介绍右值引用和移动语义, N2027是一个不错的教程。 N2027太长而无法在此处粘贴,但又足够短以方便阅读。 std::string遵循N2027中规定的基本原则,使您可以无罪地传递它。 您可以在Widget遵循相同的设计模式。

通常,您可以通过将const引用返回给成员变量来避免复制。 例如:

class Circle {
    Point center;
    float radius;
public:
    const Point & getCenter() const { return center; };
};

这等效于执行中的return &center ,实际上可能会内联,只是导致调用者对成员的直接(只读)访问。

如果您构造了一个临时文件以返回,则编译器可能会将多余的副本作为一种优化而删除,不需要您使用特殊的语法。

默认情况下,您应该只按值传递事物。 如果某个函数不需要修改或复制参数,则可以由const& ,否则可以按值获取参数。 按值返回对象,并将其保留以移动语义或RVO以避免复制。


C ++使用并鼓励按“值”传递对象。 移动语义是一项功能,它允许代码在进行复制的同时比引入之前减少副本。 通常,代码无需直接使用右值引用类型即可获得移动语义的好处。 这是因为临时对象是右值,并且重载解析将自动选择采用右值引用的方法。

例如:

std::string getStr(){
   return "Hello";
}

std::string hello = getStr();

此代码使用移动语义。 return "Hello"构造一个临时字符串,因此用于初始化返回值对象的构造函数将是move构造函数(尽管实际上,返回值优化几乎肯定会避免此移动)。 然后, getStr()返回的值是一个临时值,因此为string hello选择的构造函数再次是move构造函数。

我认为您也可以执行std::string &&hello = getStr(); ,但这可能不是必需的,因为hello已经被移动构造了。

我能想到的另一种方法是使用共享指针

除非您真的需要智能指针提供的特定所有权语义,否则我认为智能指针通常不是一个好主意。 使用简单的“按值”传递是一个很好的默认值,并且移动语义通常允许您无需额外复制就可以使用它。

如果不使用构造函数设置它们,是否还建议将类中的字段作为右值引用?

不,成员推荐通常不是一个好主意。 它们使事情变得更加复杂,并且您甚至无法如示例所示使用它们。 如果您的示例代码被允许,则sh.str = getStr(); 这将是未定义的行为,因为您正试图分配给不存在的对象。 就像std::string *str; *str = getStr(); std::string *str; *str = getStr();

右值引用将更快,因为它们是语言的固有功能,而不是引用计数类。 在此处使用智能指针或共享指针不会带来任何收益,并且会大大降低清晰度。 但是,右值引用是为此类语言设计的一部分。 使用右值引用。

如果要在这种情况下使用智能指针,也许unique_ptr是更好的选择。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM