没有可用的拷贝构造函数或拷贝构造函数被声明为'explicit'。

8
请问有人能解释一下为什么我在这里会收到编译错误 - 错误C2558:类'std::auto_ptr<_Ty>':没有可用的复制构造函数或复制构造函数被声明为'explicit'。
#include <memory>
#include <vector>
#include <string>
template<typename T>
struct test
{
    typedef std::auto_ptr<T> dataptr;
    typedef std::auto_ptr< test<T> > testptr;
    test( const T& data ):
    data_( new T(data) )
    {
    };
    void add_other( const T& other )
    {
        others_.push_back( testptr( new test(other) ) );
    }
private:
    dataptr data_;
    std::vector< testptr > others_;
};

int main(int argc, char* argv[])
{
    test<std::string> g("d");

    //this is the line that causes the error.
    g.add_other("d");

    return 0;
}

我已经有一段时间没有写C++了,但是应该是g = test<std::string>("d");,对吧? - Jesse Jashinsky
@Jesse J:两种方法都可以。这两种方式的行为略有不同,但除非是最恶劣的情况,否则结果相同。从技术上讲,您的方法将创建一个测试类,然后将其分配给g,而不仅仅是初始化g本身。仅当您具有自定义复制/赋值/初始化行为时,才会出现问题。 - Akusete
谢谢大家。非常有启发性的回答。 - Carl
4个回答

7
基本上,std::auto_ptr 不能以这种方式使用。
others_.push_back( testptr( new test(other) ) );

需要确保存在一个接受const&的复制构造函数,而std::auto_ptr却没有这样的构造函数。这被普遍认为是一件好事情,因为你不应该在容器中使用std::auto_ptr如果你不明白为什么,请阅读Herb Sutter的这篇文章,特别是其中关于不应该做的事情和原因的章节,大约在文中间的3/4处。

1
如果强制要求标准容器使用 swap 来复制内容,那么 auto_ptr 就能正常工作了。我真的希望如此。在 C++0x 中,::std::unique_ptr(非常类似于 ::std::auto_ptr)也没有拷贝构造函数,只有移动构造函数。标准容器被强制使用移动构造函数来移动其内容,因此您可以将 ::std::unique_ptr 存储在其中,并使其按预期工作。 - Omnifarious
事实上,在容器中使用auto_ptr是非法的,因为STL容器要求其成员具有“正常”的复制行为,而auto_ptr不符合该要求。 - Billy ONeal
1
@Omnifarious:你把shared_ptr和unique_ptr混淆了。Shared_ptr是一个引用计数智能指针,而不是具有移动语义的指针。 - Billy ONeal
@Billy - 如果你这样做,代码警察会来抓你吗?还是只会导致编译器错误?哦!你关于shared_ptr的想法是对的。我现在会修复它。 - Omnifarious
@Omnifarious:嗯...你会如何构建容器,以便对其迭代器的任何任意操作都始终使用交换语义?你可以在存储重新分配方面做到这一点,但在一般情况下却不行。 - Billy ONeal
显示剩余3条评论

6

4

您不能创建auto_ptr的标准库容器,就像您在这里尝试的那样:

std::vector< testptr > others_;

因为它们没有正确的语义,所以你将不得不使用普通指针或者不同类型的智能指针,例如 shared_ptr


2
如果您有使用gcc 4.5+编译器的话,您可能想要使用即将推出的C++0x标准中的std::unique_ptr或std::shared_ptr,它们将替代auto_ptr。以下是相关链接:std::unique_ptrstd::shared_ptr。请注意保留HTML标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接