Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 复制C++;使用引用类型的成员变量初始化_C++ - Fatal编程技术网

C++ 复制C++;使用引用类型的成员变量初始化

C++ 复制C++;使用引用类型的成员变量初始化,c++,C++,我有一个类,它存储对其父类的引用,该引用在构造函数中传递。如果我试图复制一个实例,我会得到一个错误“error C2582:'operator='function is unavailable”,可能是因为引用不可赋值 有没有办法解决这个问题,或者我只是将变量改为指针而不是引用 e、 g(过于简化,但我认为有要点): 是的,只需将成员设置为指针。引用将无法重置,并且没有解决方法 编辑:@“Steve Jessop”有效地指出了如何使用PIMPL习惯用法(使用“d指针”的私有实现)解决问题。在赋值

我有一个类,它存储对其父类的引用,该引用在构造函数中传递。如果我试图复制一个实例,我会得到一个错误“error C2582:'operator='function is unavailable”,可能是因为引用不可赋值

有没有办法解决这个问题,或者我只是将变量改为指针而不是引用

e、 g(过于简化,但我认为有要点):


是的,只需将成员设置为指针。引用将无法重置,并且没有解决方法


编辑:@“Steve Jessop”有效地指出了如何使用PIMPL习惯用法(使用“d指针”的私有实现)解决问题。在赋值中,您将删除旧的实现,并创建一个由源对象的d指针构造的新副本

是的,如果您需要支持赋值,将其作为指针而不是引用几乎是您唯一的选择。

我会将其作为boost::shared\u ptr。你可以很粗暴地对待他们,他们会照顾好自己。而使用原始指针意味着您必须担心该对象保持活动状态

您需要实现一个复制构造函数并初始化该复制构造函数中的引用,以指向与原始对象相同的引用。

我不建议这样做 但如果你真的很想这么做:

#include <new>

MyClass::MyClass(const MyClass &rhs): parent(rhs.parent)
{
}

MyClass &MyClass::operator=(const MyClass &rhs)
{
    if (this!=&rhs)
    {
        this->~MyClass();
        new (this) MyClass(rhs);
    }

    return *this;
}
#包括
MyClass::MyClass(常量MyClass&rhs):父级(rhs.parent)
{
}
MyClass和MyClass::operator=(常量MyClass和rhs)
{
如果(此!=&rhs)
{
这个->~MyClass();
新(本)MyClass(rhs);
}
归还*这个;
}

有一种方法可以做到这一点,但仍然要使用引用,请使用
引用\u包装
。所以

    T& member;
变成

    std::reference_wrapper<T> member;
std::reference\u包装器成员;

引用包装器基本上只是可重新分配的引用。

正如其他人提到的,可以使用std::Reference\u包装器。也可以使用辅助函数std::ref()和std::cref()。与其他帖子不同,C++03在名称空间std::tr1中引入了reference_wrapper、ref()和cref(),因此如果不使用C++11或更高版本,您可以选择使用它们。

可能编译器与相同的参数和成员名混淆了?引用始终是常量。一旦(在构造函数中)为其赋值,就不可能更改其值。所以,如果你想支持矫揉造作,你可以把它变成一个指针。“没有解决办法”。正因为如此,我将要提到错误实现
操作符=
的可能性,即显式调用析构函数,然后使用placement new和copy构造函数进行构造。或者更有效地使用pimpl并让
操作符=
进行复制和交换。impl本身不需要
操作符=
,仍然可以使用引用。尽管如此,如果这是pimpl唯一需要的功能,那么要编写的样板文件还是很多…@Steve Jessop:对不起,请你再解释一下。我不确定我是否理解这个问题workaround@Chubsdad其思想是,您的类将类似于
classmyclass{classpimpl;Pimpl*p;public:/*dtor和ctors…*/void swap(MyClass&m);MyClass(MyClass const&m);MyClass&operator=(MyClass m);}和C++文件<代码>类MyCase::PIML{{Prime/Prime};};MyClass::MyClass(MyClass const&m):p(新的Pimpl(*m.p)){}MyClass和运算符=(MyClass m){swap(m);返回*this;}无效MyClass::swap(MyClass&m){std::swap(p,m.p);}
。这在某种程度上可以被视为一种“变通方法”,我怀疑:)是的,他说了什么,但更多的断线;-)。正如我所说的,为了避免指针,这是一大堆样板文件,经过反思,litb是对的:如果这是一个解决方案,那么这将是一个非常漫长的过程。但“新Pimpl(*m.p)”是否会将原始拷贝重新引入我们?我认为这种方法只是将问题从MyClass转移到Pimpl,而没有在任何地方实际解决它。不确定我是否还懂。这和使用参考资料没什么区别。。。无论是使用引用还是原始指针,您都必须相信引用的对象仍然存在。这完全不同。只要有人指向对象,boost shared_ptr就会保持对象的活动状态,而原始指针或引用则不会。问题是,这通常会运行到引用循环中(子对象指向父对象,父对象指向子对象),这将导致引用计数从不下降到0,并且在没有其他引用的情况下对象会泄漏。您可以通过将其中一个指针设置为
弱\u ptr
来避免问题,但在使用时必须检查它。如果C++11及更高版本可用,这似乎是最好的方法。这应该是现在公认的答案。以最好的方式解决了我所有的问题。非常感谢!这个答案只教会了我很多C++!现在一切都有意义了。这比指针要好得多,因为您清楚地告知
成员
-值不能为空。如果是指针,其他人总是要问自己指针为null是否有效。警告:这种方法是未定义的行为。“如果在原始对象占用的存储位置创建了一个新对象,……将自动引用该新对象,并且在新对象的生命周期开始后,可用于操作该新对象,如果:……原始对象的类型不是常量,并且如果是类类型,则不包含任何非常量-类型为常量或引用类型的静态数据成员…”
    std::reference_wrapper<T> member;