![](/img/trans.png)
[英]Passing object from another class to a constructor of the other in C++?
[英]C++: Passing object to class constructor, how is it stored?
考虑以下在 C++ 中实现的简单 class 示例。
foo.hpp
#include <vector>
class Foo {
private:
std::vector<double> X;
public:
Foo() = default;
~Foo() = default;
Foo(std::vector<double>&);
};
foo.cpp
#include "Foo.hpp"
Foo::Foo(std::vector<double>& X):
X(X)
{}
在这种情况下,向量 X 通过引用传递给 class Foo 的构造函数。 不过,我开始怀疑实现中的操作 X(X) 是否会复制并将其“粘贴”到 class 的成员 X 中。
它是哪一个?
是的,数据成员X
将从构造函数参数X
复制初始化。
如果将数据成员X
声明为引用,则不会发生复制操作。 例如
class Foo {
private:
std::vector<double>& X;
public:
~Foo() = default;
Foo(std::vector<double>&);
};
Foo::Foo(std::vector<double>& X):
X(X)
{}
然后
std::vector<double> v;
Foo f(v); // no copies; f.X refers to v
Rest 放心。 该成员的类型是vector<double>
,因此编译器将在vector<double>
class 中查找与提供的参数类型( vector<double>&
)匹配的构造函数重载。
它会找到的最佳匹配是const vector<double>&
重载 - 复制构造函数。
作为替代方案,您可以为 class 创建一个带有右值引用的构造函数:
#include <vector>
class Foo {
private:
std::vector<double> X;
public:
Foo() = default;
~Foo() = default;
Foo(const std::vector<double>&);
Foo(std::vector<double>&&);
};
然后构造函数将像这样实现:
Foo::Foo(std::vector<double>&& X_) : X(std::move(X_)) {}
调用此构造函数时不进行任何复制。
在您的示例中, X ( Foo 类的成员)是copy-constructed
。 防止复制的一种解决方案是将 X 定义为 Foo class 中的lvalue reference
,尽管它不是适用于所有情况的通用解决方案,并且如果原始 X 的 scope 为当 Foo 还活着时完成,总而言之,根据您的应用程序,您有以下选项之一
使用对 X 的lvalue reference
,如果每个可能的 Foo object 的 scope 低于传递的 object (X):
foo.hpp
#include <vector> class Foo { private: std::vector<double> &X; public: Foo() = default; ~Foo() = default; Foo(std::vector<double>&); };
foo.cpp
#include "Foo.hpp" Foo::Foo(std::vector<double>& X): X(X) // keep the lvalue refrence to the passed Object {}
然后
std::vector<double> v;
Foo f(v); // no copies; f.X refers to v
// Foo function calls including f.X should be finished before destruction of the v Object
将 X 转换为rvalue reference
(std::move) 并将其移动到 Foo class 的成员 X,如果在 Foo 构造函数调用之后通过传递的 Object 名称不应该使用 X 内容:
foo.hpp
#include <vector> class Foo { private: std::vector<double> X; public: Foo() = default; ~Foo() = default; Foo(std::vector<double>&&); };
foo.cpp
#include "Foo.hpp" Foo::Foo(std::vector<double>&& X): X(X) // move constructor of std::vector<double> is called in this line {}
然后
std::vector<double> v = {1.0, 2.0, 3.0};
Foo f(std::move(v)); // no copies; f.X use resource of v, but v is empty now
// v is empty now
最后一种方法与您的实现完全相同。 在这种情况下: foo.hpp
#include <vector> class Foo { private: std::vector<double> X; public: Foo() = default; ~Foo() = default; Foo(const std::vector<double>&); };
foo.cpp
#include "Foo.hpp" Foo::Foo(const std::vector<double>& X): // using const is better: in this case X(X) // copy constructor of std::vector<double> is called in this line {}
然后
std::vector<double> v = {1.0, 2.0, 3.0};
Foo f(v); // do copies; f.X copy the resource of v, and v is still valid
话虽如此,根据情况,所有这些方法都有自己的应用程序。 为了清楚起见,只需简单地应用此优先级规则:
1-通过rvalue reference
传递,这导致成员的move constructor
。 (例如,当您想将 object 传递给 std::thread 构造函数时,以及所有权,即资源,以及资源生命周期。)。
2-传递lvalue reference
并保留它,当传递的 object 生命周期(在这些示例中为 v)大于引用的生命周期时。
3- 传递const lvalue reference
并调用copy constructor
copy constructor
在这些示例中为std::vector
的复制构造函数),当最后的选择不适用时,或者由于进一步使用传递的lifetime
或由于通过 Object。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.