#include <iostream>
#include <vector>
#include <array>
#define Nbodies 3
class Assembly {
public:
// initializing constructor
Assembly(double _dataA)
: data(_dataA), AssA(nullptr), AssB(nullptr) { }
// double argument copy constructor
Assembly(Assembly &A, Assembly&B)
: AssA(&A), AssB(&B) {
data = A.data * B.data;
}
// single argument copy constructor - generates errors once uncommented
/*
Assembly(Assembly &A)
: data(A.data), AssA(&A), AssB(&A) {
// initialize other members of this class here
}
*/
double data;
private:
// these are const pointers to non-const objects of a type Assembly
Assembly *const AssA, *const AssB;
};
int main() {
std::array<double, Nbodies> datas = {1.0, 2.0, 3.0};
// Initilize first branch of the binary tree
std::vector<Assembly> base_assembly;
for (int i = 0; i < Nbodies; i++) {
base_assembly.emplace_back(datas[i]);
}
// Binary tree assembly - MWE (for general case, I'm using nested for loop)
Assembly AssemblyAB = Assembly(base_assembly[0], base_assembly[1]);
Assembly AssemblyC = Assembly(base_assembly[2]);
Assembly AssemblyS = Assembly(AssemblyAB, AssemblyC);
std::cout << AssemblyS.data << std::endl;
return 0;
}
我正在研究一个程序,该程序递归地生成二进制尝试。当我有一个带有奇数个元素的分支时,我需要将一个元素“重写”到一个较低的分支。为此,我使用了一个拷贝构造函数,因为我需要初始化该类的其他成员(我使用的是Eigen库,并且某些操作不能作为初始化列表中的单行代码完成)。
当我定义一个单参数复制构造函数时,我的问题出现了。我收到以下错误:
... / mingw64 / lib / gcc / x86_64-w64-mingw32 / 8.1.0 / include / c ++ / bits / stl_construct.h:75:7: 错误:
无法将“ Assembly&”类型的非常量左值引用绑定到 类型为“ Assembly”的右值
为什么定义单个参数副本构造函数会产生这样的错误?请注意,对于具有两个参数的副本构造函数,根本没有错误。
答案 0 :(得分:1)
典型的复制构造函数采用const T&
,或者在这种情况下为const Assembly&
。
由于您没有该类型,因此无法使用std::vector
之类的标准库容器来复制您的类型,如果需要重新分配数组(例如使其变大),则需要这样做。
但是,std::vector<T>
(其中T
具有noexcept移动构造函数)将改用move构造函数,从而避免了没有复制构造函数的问题。
因此,以下新增功能可以使其工作:
Assembly(Assembly&&) noexcept = default; // generate a noexcept move constructor
请注意,这将导致新构造的对象也指向相同的AssA
和AssB
对象。
作为旁注,我建议将它们重命名为AsmA
和AsmB
(如果只是为了防止窃笑)。
编辑:
从根本上讲,问题在于单个参数Assembly&
的构造函数,这导致不会隐式生成副本构造函数。由于不直观,与副本构造函数的相似性也很差。当您希望Assembly thing = other;
仅复制它时,实际上会调用Assembly&
这个奇怪的构造函数。因此,解决该问题的最佳答案就是摆脱它。
选项1:当您想要这种行为时,只需使用2参数构造函数并将同一对象传递两次即可。
选项2:使其成为标签构造函数:
// the tag type we'll use to select the weird constructor
inline struct same_asm_t {} same_asm; // not sure what version of C++ you're on; if this doesn't work remove inline and define in a cpp file elsewhere
// define this as a tag constructor (take some other "tag" type as a param for overload resolution)
Assembly(Assembly &A, same_asm_t) : data(A.data), AssA(&A), AssB(&A) {}
// use it like this, where other is an instance of Assembly
Assembly thing(other, same_asm);