我尝试将std::unique_ptr
传递给继承的类,该类将它转发给基类构造函数(使用构造函数初始化列表)。如果基类构造函数接收到nullptr
,则应构造默认对象并将其分配给我的基类的std::unique_ptr
成员变量。但不知怎的,我得到了一个AccessViolation,如果我试图从任何地方std::unique_ptr
访问任何元素(因为它仍然是nullptr
- 即使此时不可能这样做。)
这里有什么想法吗?
#include <iostream>
#include <memory>
class C{
public:
int x;
};
class A{
public:
A(std::unique_ptr<C> c) : c(std::move(c)){
if(c == nullptr){
c = std::unique_ptr<C>(new C);
c->x = 1;
}
}
void print(){
std::cout << c->x << std::endl;
}
private:
std::unique_ptr<C> c;
};
class B : public A{
public:
B(std::unique_ptr<C> c) : A(std::move(c)){
}
};
int main(int argc, char* argv[]){
B b(nullptr);
b.print();
return 0;
}
答案 0 :(得分:3)
在A::ctor
中,您使用的是变量c
,但它不是引用类成员A::c
,而是引用作为ctor参数的局部变量c
。因此,在ctor退出后,A::c
将为nullptr
,因此您无法在A::print
函数中取消引用它。
A(std::unique_ptr<C> c) : c(std::move(c)){
if(c == nullptr) { // here c is ctor parameter (local variable)
c = std::unique_ptr<C>(new C); // A:c is still nullptr
c->x = 1; //
}
}
可能的解决方案是为局部变量c
名称和A::c
创建不同的名称,例如A::m_c
。
答案 1 :(得分:2)
如果你不想在构造函数中做任何额外的工作,并且提供基础的所有可能的构造函数都不是问题,请使用继承构造函数。
class B : public A {
using A::A;
};
答案 2 :(得分:1)
您发生的变数非常糟糕。
构造函数的参数与成员变量的名称相同。因此,只在构造函数体中创建构造函数的变量,并且在初始化列表中分配成员变量,无论您传递什么(在您的情况下为nullptr)。
要解决此问题,请重命名构造函数的参数:
A(std::unique_ptr<C> c1) : c(std::move(c1)){
if(c == nullptr){
c = std::unique_ptr<C>(new C);
c->x = 1;
}
}