在C ++中,我有一个构造函数,它接受类descriptor
的对象。这个类最近增长了,我需要通过参考更多地传递它。如果我通过引用将它传递给下面的ctor,那么成员仍会自己制作副本,因为它没有被声明为引用类型吗?
descriptor taskedStats;
public:
CWorkerThread(int ticketNumber, int threadNumber, descriptor taskedStats) :
_pPaginatableForm(pPaginatableForm), ticketNumber(ticketNumber)
, threadNumber(threadNumber), taskedStats(taskedStats) {}
或
descriptor taskedStats;
public:
CWorkerThread(int ticketNumber, int threadNumber, descriptor &taskedStats) :
_pPaginatableForm(pPaginatableForm), ticketNumber(ticketNumber)
, threadNumber(threadNumber), taskedStats(taskedStats) {}
答案 0 :(得分:2)
你的构造函数会复制,无论如何。如果你通过值传递,那么你可能会制作2份副本,但是编译器可能会优化其中一个。
但更好的选择是接受一个const引用,即
CWorkerThread(int ticketNumber, int threadNumber, descriptor const& taskedStats) :
_pPaginatableForm(pPaginatableForm),
_ticketNumber(ticketNumber),
_threadNumber(threadNumber),
_taskedStats(taskedStats)
{}
当然,一旦我们进入C ++ 11的世界并移动构造函数,您就不需要复制任何副本,只要不再需要传入的副本。即使现在也有办法做到这一点,但需要在对象内部进行特殊的“黑客攻击”,或使用智能指针。
答案 1 :(得分:2)
类成员被声明为一个对象,所以它是一个对象。
传递给构造函数的引用将用于使用其复制构造函数初始化成员。
最好尽可能通过const
参考;这表明构造函数不会修改参数,也允许您传递临时值。
答案 2 :(得分:1)
参数从descriptor
更改为descriptor&
仍会导致成员变量taskedStats
从参数taskedStats
复制(使用复制构造函数)。
要避免副本,您可以将成员变量taskedStats
设为descriptor&
,但这意味着参数taskedStats
必须在有效期内有效CWorkerThread
对象(在这种情况下,不会使参数taskedStats
成为const descriptor&
会阻止临时对象的传递。)
答案 3 :(得分:0)
编译器提供的默认或隐式复制构造函数构成所有成员的浅表副本,并具有以下签名:
descriptor(const descriptor &other);
因此传递对描述符的引用与尝试(用C语言)传递副本没有什么不同 - 它们实际上只是通过引用传递。
如果成员被声明为引用类型,那么就像指针一样,它的类型在上面的隐式复制构造函数中将不匹配,并且将执行引用赋值,从而使任何创建本地副本的尝试无效在每个对象中。