gpt4 book ai didi

c++ - std::string 在类对象内部的函数中传递时丢失值

转载 作者:行者123 更新时间:2023-11-28 00:26:06 27 4
gpt4 key购买 nike

我真的很困惑编译器如何分配 STL 对象。考虑以下代码:

#include <string>

using namespace std ;

class s {
public:
string k ;

s(string k) : k(k) {}
} ;

void x ( s obj ) {
string k = (obj.k) ;
k += "haha" ;

}



int main () {
std::string mystr ("laughter is..") ;
s mys(mystr) ;
x(mys) ;

printf ("%s", mystr.c_str() ) ;
}

这个程序的输出是 laughter is.. 我希望输出是:笑是哈哈

为什么 mystr string 没有得到 haha 。我需要将它作为代码的一部分存储在一个类中。

如果我按值将 mystr 传递给函数 x,字符串 mystr 就会得到 haha

a) 如何以及何时分配 STL 对象?我假设 mystr 在堆栈上,并且必须可供从 main() 调用的所有函数访问。

b) 如果我需要将 STL 对象存储在需要“void*”的老式链表中怎么办?我不能这样做吗:

std::string mystr ("mystring.." );

MyList.Add((void*)&mystr) ;

fun(MyList) ;

函数是否有趣,现在通过访问 MyList 使用和修改 mystr ?

c) 作为 (b) 的替代方法,我可以使用引用传递吗?问题是我可以声明一个类来保留对 mystr 的引用吗?我的意思是 MyList 的构造函数可以是这样的:

class MyList { 
string& mStr ;
...
};


MyList::MyList ( string& mystr ) {
mStr = mystr ;

}

那个构造函数有效吗?该类(class)有效吗?

最佳答案

你的类(class)只是让你的情况复杂化。你在这里有完全相同的问题:

void x ( string str ) {
str += "haha" ;
}

int main () {
std::string mystr ("laughter is..") ;
x(mystr) ;

printf ("%s", mystr.c_str() ) ;
}

我已经摆脱了这门课。而不是把 mystr进入 s对象并传递 s反对 x , 我刚刚通过 mystr直接地。 x然后尝试添加 "haha"到字符串。

问题是 x按值获取其参数。如果你按值传递一个对象,你将得到它的一个拷贝。即 str object 与 mystr 是不同的对象.它是它的拷贝,但它是一个不同的对象。如果修改str ,你不会影响 mystr完全没有。

如果你想要x为了能够修改它的参数,你需要让它引用:

void x ( string& str ) {
str += "haha" ;
}

不过,我明白你为什么要介绍这门课。您在想“好吧,如果我将字符串提供给另一个对象,然后将该对象传递给该对象,则该字符串在函数外部和内部都应该相同。”事实并非如此,因为您的类(class)正在存储字符串的拷贝。也就是说,你的类(class)有一个成员 string k;这将是该类类型的任何对象的一部分。字符串 kmystr 不是同一个对象.

如果你想在函数之间修改对象,那么你需要某种形式的引用语义。这意味着使用指针或引用。

关于您的问题:

  1. 是的,string对象 mystr在堆栈上。不过,这与它来自标准库无关。如果你在一个函数中写一个声明,那个对象就会在栈上,不管它是int x;。 , string s; , SomeClass c; ,或其他。

    数据内部存储里面mystr另一方面,是动态分配的。一定是因为 std::string 的大小可以变化,但 C++ 中的对象始终具有固定大小。一些动态分配是必要的。但是,您不需要关心这个。此分配由类封装。你可以只对待mystr作为字符串。

  2. 请不要使用存储void* 的链表秒。使用 std::list反而。如果你想要一个字符串链表,你需要 std::list<std::string> .但是,是的,如果您有一个对象存储指向其他一些对象的指针,并且您按值传递该对象,则拷贝中的指针仍将指向相同的位置,因此您仍然可以修改它们指向的对象。

  3. 如果你有一个 std::list<std::string>而你想把它传递给一个函数,让函数可以修改容器的内容,那么你需要通过引用传递它。如果您还需要列表的元素引用您在列表外创建的对象,则需要使用 std::list<std::reference_wrapper>相反。

    就初始化引用成员而言,您需要使用成员初始化列表:

    MyList::MyList(string& mystr)
    : mStr(mystr)
    { }

关于c++ - std::string 在类对象内部的函数中传递时丢失值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24980213/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com