2012-04-18 52 views
1

我该如何去使用构造函数来处理一个字符串的成员?下面是一个例子(这是不对的我知道)C++字符串成员构造

class Filestring { 
public: 
    string  sFile; 

    Filestring(const string &path) 
    { 
     ifstream filestream(path.c_str()); 
     // How can I use the constructor for the member sFile?? 
     // I know this is wrong, but this illustrates what I want to do. 
     string sFile((istreambuf_iterator<char>(filestream)), istreambuf_iterator<char>()); 
    } 
}; 

所以基本上我希望能够使用成员sFile的构造而不做字符串拷贝。有没有办法通过分配来实现这一点?

+2

你为什么这么关心一个字符串复制?如果您正在从文件中读取数据,则文件I/O时间将占用大部分运行时间。 – 2012-04-18 19:58:46

+0

只是为了清楚这一点?你是否试图用文件的内容初始化sFile? – smichak 2012-04-18 20:01:03

+0

@smichak正确 – grep 2012-04-18 20:07:58

回答

3

你可以使用的最好的是string::assign

sFile.assign(istreambuf_iterator<char>(filestream), istreambuf_iterator<char>()); 

但在C++ 11有字符串的举动赋值运算符这样做下面几乎是不作为有效的(没有字符数据的副本,字符数据被移动):

sFile = string(istreambuf_iterator<char>(filestream), istreambuf_iterator<char>()); 

当C++ 11移动任务无法使用时,又一个窍门是使用std::swapstring::swap。效率可能与移动赋值变体几乎相同。

string newContent(istreambuf_iterator<char>(filestream), istreambuf_iterator<char>()); 
std::swap(sFile, newContent); // or sFile.swap(newContent); 
1

不是真的,如果您不初始化初始化程序列表中的成员(在您的情况下似乎不可能),那么您一定会做一个副本。

请注意,您的代码不会初始化成员,但会创建一个新的局部变量。

正确的方法是

sFile = std::string((istreambuf_iterator<char>(filestream)), istreambuf_iterator<char>()); 
0

使用初始化列表:

Filestring(const string &path):sFile(/*what you're initializing with*/) 
{//more 
} 
+0

他正在用文件的内容初始化它,所以文件需要在初始化'sFile'之前打开。 – Praetorian 2012-04-18 20:00:02

+0

@PrætorianTrue;然而,在建造琴弦之前不可能这样做(即,在更早的类成员的ctor中)并将该对象中的内容传递给字符串ctor,所有这些都在初始化程序列表中? – tmpearce 2012-04-18 20:02:10

+0

不是课程目前实施的方式。如果他将'ifstream'作为成员变量*并在'string'成员变量之前声明它(顺序很重要),那么可以打开文件并在'Filestring'构造函数的初始化列表中构造该字符串。 (顺便说一句,我没有downvote :-)) – Praetorian 2012-04-18 20:16:27

0
sFile.assign(constructor args); 
1

你可以做到这一点。
但它不值得额外的复杂性。如果你想避免一个副本的成本(一个体面的编译器可能会做的)。你可以将它加载到一个临时的然后使用std :: swap()。

我会做:

class Filestring { 
public: 
    string  sFile; 

    Filestring(const string &path) 
    { 
     ifstream filestream(path.c_str()); 
     string data((istreambuf_iterator<char>(filestream)), istreambuf_iterator<char>()); 

     // Just swap the internal data structures: 
     std::swap(sFile, data); 
    } 
}; 
3

一种方法是让FILESTREAM的成员,因此它可以在构造函数初始化列表被称为:

class Filestring { 
private: 
    ifstream filestream; 
public: 
    string  sFile; 

    Filestring(const string &path) : filestream(path.c_str()), sFile((istreambuf_iterator<char>(filestream)), istreambuf_iterator<char>()) 
    {} 
}; 

为此才能正常工作,文件流必须出现在sFile之前类定义,否则它不会被及时初始化以在sFile构造函数中使用它。当然,你也增加了Filestring类的开销。

一个更安全的技术,这也避免了串复制的开销是使用字符串::互换():

class Filestring { 
public: 
    string  sFile; 

    Filestring(const std::string &path) 
    { 
     std::ifstream filestream(path.c_str()); 
     sFile.swap(string((istreambuf_iterator<char>(filestream)), istreambuf_iterator<char>())); 
    } 
}; 
+0

交换速度会快于sFile = string(istreambuf_iterator (filestream),istreambuf_iterator ());'? – grep 2012-04-18 20:18:30

+0

在第一个示例中,如果将其构建为'sFile'的初始化程序中的临时文件,则可以避免私有的'filestream'元素。这样可以避免元素需求的顺序,如果班级增长并且有人想整理它,这些元素就会出现错误。 – bjhend 2012-04-18 20:45:44

+1

这就是我想要的(但没有完全阐明)在我的答案... +1 – tmpearce 2012-04-19 02:30:04