如何使用在函数中本地创建的对象而不将其复制到内存中
How to use object that created locally in a function without copying it in memory?
例如,我有一个类,它在返回本地对象的构造函数中调用函数。我正在尝试使用右值引用来访问这个对象,以避免在内存中昂贵地移动它。
class MyClass
{
BigObject&& C;
MyClass() : C(f())
{
};
};
BigObject f()
{
return BigObject();
}
但compiller告诉我,引用成员被初始化为一个临时成员,该成员在构造退出后不会持久存在。
我不明白。我知道在函数范围内创建的局部对象只存在于函数范围内。到达作用域的末尾时,将调用局部对象的析构函数。在这里,我用本地对象初始化右值引用,当我在constructor的主体中时,我可以访问它。
有人能解释一下吗,这里发生了什么事?有没有一种方法可以返回本地对象并将其用作任何可照明的类成员,而不在内存中移动它?
您应该从C
中删除&&
。
代码并不像您想象的那么昂贵:f
的返回值是一个复制省略上下文。因此,编译器可以直接在C
的内存空间中构造一个BigObject
。即使编译器不执行此操作,它仍然是一个移动上下文,因此在最坏的情况下,对象将被移动。
如果你的对象是可复制的,但不能移动,那么你必须依赖于复制省略,但很难想象这样一个对象的有效用例。
要引用标准中的内容,
第12.2.5节
第二个上下文是引用绑定到临时的。引用绑定到的临时或临时的,是子对象的完整对象引用在引用的生存期内保持绑定,但以下情况除外:--构造函数中引用成员的临时绑定ctor初始值设定项(12.6.2)一直存在,直到构造函数退出。
所以,在"C(f()"的情况下,C只绑定到临时,直到构造函数退出,然后它就变成了UB,这取决于你的运气。您应该感谢编译器报告了一个警告:)。
无论如何,没有必要做这样的杂技,但你总是可以从临时变成C。
class BigObject
{
public:
BigObject() {std::cout << "Cons" << std::endl;}
BigObject(const BigObject& other) {std::cout << "Copy Cons" << std::endl;}
BigObject(BigObject&& other) {std::cout << "Move Cons" << std::endl;}
};
BigObject f()
{
return BigObject();
}
class MyClass
{
public:
BigObject C;
MyClass() : C(f())
{
};
};
在这种情况下,编译器只需在目标站点构造一次"BigObject",就可以很好地消除副本,使代码尽可能高效。
因此,在这种特殊情况下,可能您的对象根本没有移动,甚至没有复制。也许这就回答了你的最后一个问题。
- 为什么C++在将一个对象复制到另一个对象时需要对这两个对象进行低级常量限定
- 如何在向量列表初始化时避免对象复制以及如何延长临时的生存期
- 了解在 C++ 中分配容器时的对象复制
- C++类对象复制构造函数和运算符=
- 复制 elision/RVO 会导致从同一对象复制/移动吗?
- 如何在循环内将大对象复制到omp任务中?
- 为什么当我添加一个不同的对象(复制构造函数中的参数)时调用复制构造函数?
- 无法将类构造函数中新创建的对象复制到 C++ 中的向量成员
- 将C++对象复制到指向新指针的指针处
- 将一个 OpenCV OutputArrayOfArrays 对象复制到另一个对象
- 选择性地禁用隐式对象复制
- 不能从文件到指针向量的对象复制
- 从派生对象复制构造
- OpenCV Mat对象复制速度更快
- 将子对象复制到父对象
- 为什么普通的 c++ 编译器不优化对象复制?
- C :将一个对象复制到构造函数中的另一个对象
- 使用命名对象复制构造函数
- 不必要的对象复制 - C++ STL
- 如何将一个类的对象复制到另一个类中