【发布时间】:2010-01-20 09:28:23
【问题描述】:
请考虑以下几点:
class CMyClass
{
public:
CMyClass()
{
printf( "Constructor\n" );
}
CMyClass( const CMyClass& )
{
printf( "Copy constructor\n" );
}
};
int main()
{
std::list<CMyClass> listMyClass;
listMyClass.resize( 1 );
return 0;
}
它产生以下输出:
构造函数
复制构造函数
现在我的问题是:如何避免复制构造函数?或者换一种说法:如何在没有不必要的复制操作的情况下在 STL 容器中创建对象。有没有办法使用默认构造函数进行“就地”构造?
更新 - 到目前为止的答案:
- 做不到
- 使用指针或智能指针 而是。
智能指针对我的应用程序来说太过分了。但我真的很想知道为什么不能这样做。这似乎是一件显而易见的事情。还有其他想法吗?如果可行的话,我什至会接受一个讨厌的黑客攻击......
解决方案
我想我刚刚从这里提出的所有 cmets 和答案中找到了我的问题的解决方案。解决方案是构造一个空对象并保留它,唯一的目的是稍后使用它来制作干净的副本。然后,您可以使用其中一种获取引用的方法(如 push_back 或 insert)。这仍然为每个插入的新对象调用复制构造函数,但至少它不是默认构造函数和复制构造函数:
int main()
{
CMyClass Empty;
std::list<CMyClass> listMyClass;
for ( int c=0; c<10; ++c )
{
listMyClass.push_back( Empty );
}
return 0;
}
【问题讨论】:
-
这似乎是一个显而易见的事情,但从功能的角度来看,这并不重要,并且有几个算法(排序、删除、...)也使用复制,所以要准备好被复制;)(另见devx.com/tips/Tip/13606)
-
显而易见的事情?这是为什么?为什么复制有问题?
-
明显吗?如果您调用
mylist.resize(10),如果它们不是副本,您会如何期望得到十个不同的对象? -
我要做的就是在列表中构造一个新对象。 STL 所做的就是先构造一个临时对象,然后使用复制构造函数复制临时对象。这个副本是不必要的浪费时间。 mylist.resize(10) 的替代实现可以调用默认构造函数 10 次。它所做的是调用默认构造函数一次,然后调用复制构造函数 10 次。这对于 10 个对象 (10%) 来说是很小的开销,但如果您必须一次添加一个对象,则开销会增加一倍 (100%)。
-
好吧,您可能希望标准容器表现得像那样,但事实并非如此。在某些情况下,编译器可能会忽略对复制 ctor 的调用,但如果您不想依赖它,为什么不使用指针,就像每个人都建议的那样?