2012-11-13 39 views
2

我已经读过,不能存储std::auto_ptrstd::vectorboost::ptr_vector可以用来代替。我已经能够这样做了,但我不知道如何使用ptr_vector,当我不想存储指针时,而是一个结构体,它有一个指针成员。结构域上的智能指针

在这个例子中,我想打开一些文件并将关联的ofstream对象与一些额外的数据一起存储,供以后使用。我想用智能指针替换struct datafile字段。由于vector<data> v应该是所有者,我认为shared_ptr可以工作,但不合适。

我应该用什么替换裸指针file

#include <iostream> 
#include <fstream> 
#include <vector> 

struct data { 
    std::string filename; 
    std::ofstream* file; 

    data(const std::string filename, std::ofstream* file) 
    : filename(filename), file(file) 
    { 
    } 
}; 

std::vector<data> open_files() 
{ 
    std::vector<data> v; 
    v.push_back(data("foo", new std::ofstream("foo"))); 
    return v; 
} 

int main() 
{ 
    std::vector<data> v = open_files(); 

    /* use the files */ 
    *(v[0].file) << "foo"; 

    delete v[0].file; // either rely on dtor to close(), or call it manually 
} 

更新: 我觉得我已经做了在描述我的问题一个次优的工作,让我试试另一个例子。此外,我要寻找一个C++ 03的解决方案:

#include <memory> 
#include <vector> 
#include <boost/ptr_container/ptr_vector.hpp> 

struct T { 
    std::auto_ptr<int> a; 
}; 

int main() 
{ 
    // instead of 
    // std::vector<std::auto_ptr<int> > v; 
    // use 
    boost::ptr_vector<int> v; 

    // what to use instead of 
    // std::vector<T> w; 
} 
+0

在data的析构函数中做任何需要清理的操作。由于矢量不包含指针,所以你不得不采取任何行动。如果数据的析构函数是正确的,那么一切都会自行处理。 – juanchopanza

+0

为什么你需要一个(不推荐)的auto_ptr?使用boost :: shared_ptr 这是可复制的。它将由矢量所有并在矢量离开作用域时销毁。 – hhbilly

+1

'auto_ptr'模拟唯一所有权,而'shared_ptr'具有共享所有权的不同含义。如果我有权访问C++ 11,我会使用'unique_ptr'。但是使用'share_ptr'可能还是比我的版本更好。 –

回答

1

关于你的数据类,我建议使用std::unique_ptr<std::ofstream>。这不是为了避免意外内存泄漏,因为您正在删除构造函数中的指针,而是将其作为使所有权显式为。你的代码的用户必须知道什么data与它发生在构造函数中的指针做:

std::ofstream ofs; 
{ 
    data d1("crash", &ofs); 
} // error! d1 will attempt to delete stack allocated object 

std::ofstream* pOfs = new std::ofstream(....); 
data d2("crash again", pOfs); 
delete pOFs; // user thinks data makes a deep copy 

然而,随着unique_ptr的打算是明确的,所以这是很难犯错误:

data d3("OK", std::unique_ptr<std::ofstream>(new std::ofstream(....))); 

std::unique_ptr<std::ofstream> pOfs2(new std::ofstream(....)); 
data d4("OK", pOfs2); // safe, pOfs's contents have been safely moved 

// we can check pOfs2 after the move 
if (pOfs2) { /* */ } 
+0

谢谢。你也有C++ 98的建议吗? –

+0

@MichaWiedenmann不幸的是,没有一个完全令人满意的选择,但是你可以使用'std :: auto_ptr'。你必须保持私密并避免复制。你应该确保你[理解陷阱](http://www.gotw.ca/publications/using_auto_ptr_effectively.htm) – juanchopanza

+0

因为我打算把封闭类放入一个'vector',(如果'unique_ptr'不是可用)我更喜欢'shared_ptr',尽管它有不同的语义。 –

0

可以在析构函数删除指针:

struct data 
{ 
    std::string filename; 
    std::ofstream* file; 

    data(const std::string filename, std::ofstream* file) 
    : filename(filename), file(file) 
    { 
    } 
    ~data() 
    { 
    delete file; 
    } 
}; 

或者使用std::unique_ptr来包装指针,但它在你的情况是不必要的。

0

您不需要拥有ofstream *作为成员。

#include <iostream> 
#include <fstream> 
#include <vector> 

struct data { 
    std::string filename; 
    data(const std::string filename) : filename(filename) 
    {} 
}; 

std::vector<data> open_files() 
{ 
    std::vector<data> v; 
    v.push_back(data("foo")); 
    return v; 
} 

如果要追加到该文件,指定的应用程序文件模式。

void print_files(const std::vector<data>& v) 
{ 
    for(std::vector<data>::const_iterator it = v.begin(); it != v.end(); ++it) 
    { 
     std::ofstream os(it->filename, std::ostream::app); 
     os << "bar"; 
    } 
} 

int main() 
{ 
    std::vector<data> v = open_files(); 

    print_files(v); 
} 
+0

我将多次写入不同的文件,并因此提前打开所有文件。 –