返回C+中的对象+; 我从C++和java的背景中学习C++,我很好奇在C++中不需要复制对象的最好方法是什么。据我所知,C++11引入了右值引用(&&&)来从临时变量中移动数据(与复制相反)。例如: std::string getStr(){ return "Hello"; } std::string &&hello = getStr(); class StringHolder{ public: std::string &&str; }; StringHolder sh; sh.str = getStr();

返回C+中的对象+; 我从C++和java的背景中学习C++,我很好奇在C++中不需要复制对象的最好方法是什么。据我所知,C++11引入了右值引用(&&&)来从临时变量中移动数据(与复制相反)。例如: std::string getStr(){ return "Hello"; } std::string &&hello = getStr(); class StringHolder{ public: std::string &&str; }; StringHolder sh; sh.str = getStr();,c++,c++11,C++,C++11,我可以想到的另一种方法是使用共享指针 std::tr1::shared_ptr<std::string> getStr(){ std::tr1::shared_ptr<std::string> hello(new std::string("Hello")); return hello; } auto 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 Circle {
    Point center;
    float radius;
public:
    const Point & getCenter() const { return center; };
};
std::string getStr(){
   return "Hello";
}

std::string hello = getStr();
这相当于执行中的
return¢er
,事实上很可能是内联的,从而直接(只读)访问调用者的成员


如果您构造了一个临时文件以返回编译器,那么编译器可能会将额外的副本作为一种优化而忽略掉,不需要特殊的语法。

如果您想在这种情况下使用智能指针,也许unique\u ptr是一个更好的选择。

这个问题可能会作为一个重复问题来解决。这是一个经常被问到的问题。不过,我还是想回答这个问题

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

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

std::string hello = getStr();
在这个级别上,您不需要关心右值引用。只需知道,
std::string
可以从右值(例如从
getStr()
返回的值)非常有效地“复制”。此“复制”实际上称为“移动”,并自动启用,因为您是从右值(匿名临时值)复制的

不要试图通过还原到引用计数来优化复制。仅当需要共享所有权语义时才使用引用计数。这种说法并不总是正确的。但对于学习基础知识来说,这已经足够接近了,这是一个很好的经验法则

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

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

对于右值引用和移动语义的简要介绍,这是一个不错的教程。N2027太长,无法粘贴在这里,但足够短,便于阅读<代码>标准::字符串遵循N2027中规定的基本原则,使您能够无内疚地按值传递它。您可以在
小部件中遵循相同的设计模式。默认情况下,您只需按值传递内容。如果一个函数不需要修改或复制一个参数,那么它可以通过
const&
来获取,但也可以通过值获取参数。按值返回对象,并将其留给move semantics或RVO以避免复制


C++使用并鼓励“按值”传递对象。移动语义是一种特性,它允许代码执行此操作,同时生成的副本比引入之前更少。通常,为了获得移动语义的好处,代码不需要直接使用右值引用类型。这是因为临时对象是右值,重载解析将自动选择采用右值引用的方法

例如:

class Circle {
    Point center;
    float radius;
public:
    const Point & getCenter() const { return center; };
};
std::string getStr(){
   return "Hello";
}

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

我想你也可以做
std::string&&hello=getStr()
,但这可能不是必需的,因为
hello
将已被构造

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

我认为智能指针通常不是一个好主意,除非您确实需要它们提供的特定所有权语义。使用直接的“按值”传递是一个很好的默认值,移动语义通常允许您使用它而无需额外复制

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


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

您可能会发现标准库的现代实现将使用小字符串优化,因此动态分配字符串“Hello”可能比仅按值返回一个字符串慢。非常感谢!我正在慢慢理解教程和移动构造函数的概念。std中的大多数对象是否具有移动构造函数,例如向量(即,按值返回大向量是否明智)?另外,在您的示例小部件类中,“指向堆数据的指针”注释是否仅限于此示例,或者使用指针作为字段而不是值类型更常见(尽管,我会推断指针或值字段的使用取决于情况)?此外,我知道这取决于对象的移动构造函数,但我假设,一般来说,如果有obj o=std::move(p);,p可能永远不会被再次使用,对吗?@DanB91:无论如何,直到它被分配到为止。@DanB91:std::lib中可以利用move的所有对象都这样做了。这包括向量和字符串,但不复杂。对于复杂系统,没有要传输的资源(它只是一对浮点数)