我仍然在探索C ++,试图找出它是如何工作的,并遇到了令我困惑的事情。
我有一个只持有list<string>
并且有一些成员函数的类
class String_list {
public:
String_list(istream&);
//other functions
list<string> listing;
};
我编写了构造函数以使用非成员函数
String_list::String_list(istream& in) { get_strings(in, listing); }
与
istream& get_strings(istream& in, list<string> lstring)
{
if(in) {
lstring.clear();
string word;
while (in >> word)
lstring.push_back(word);
in.clear();
}
return in;
}
问题是,尽管get_string
函数似乎有效,但它不会更改我传递给它的listing
成员变量。
我只需将get_strings
更改为(istream& in)
,即可将lstring
成为listing
的成员函数,因此我可以通过构造函数中的列表由于某种原因不起作用,或者非成员函数不能更改成员变量,但这些似乎是我的编译器很容易接受的东西。
我的编译器没有看到代码的任何问题,就在我运行成员列表的.size()
为0的可执行文件时。
答案 0 :(得分:10)
您应该通过引用传递lstring
:
istream& get_strings(istream& in, list<string>& lstring)
代码编写并按原样编写:传递lstring的值,从而复制它。所有更改都在临时对象上进行,然后在对象被销毁时丢弃。
答案 1 :(得分:9)
您将成员变量的副本传递给该函数。修改本地副本,而成员变量不是。
更改get_strings
函数的签名以引用列表对象,这将有效:
istream& get_strings(istream& in, list<string>& lstring)
{
// ...
}
虽然这打破了封装,但在你的情况下(直接将成员变量暴露给该函数)。更好的方法可能是让get_strings
函数返回它填充的列表的副本,然后将其分配给初始化列表中的类成员。像这样:
list<string> get_strings(istream& in)
{
list<string> r;
// ...
return r;
}
然后你的构造函数:
StringList::StringList(istream& in) : listing(get_strings(in))
{
// ...
}
答案 2 :(得分:4)
在C ++中,除非您明确地执行,否则您将通过值传递,而不是通过引用传递。所以如果你声明你的功能:
istream& get_strings(istream& in, list<string> lstring)
然后lstring
按值传递,这意味着您没有使用在函数调用中传递的同一对象。您只需复制此对象即使您在函数体中修改它,也只需修改此副本。
如果你想修改你传递的对象,你应该通过引用传递它,你可以使用&
来实现:
istream& get_strings(istream& in, list<string>& lstring)