在探索编译器如何处理C++中的字符串时,我尝试了以下程序,该程序编译并运行时没有错误,但我不明白它是否更改了任何内存位置或对程序流有任何影响。它似乎没有任何作用。
#include <iostream>
using namespace std;
string str = "this is public stringn";
string foo() {
return str;
}
int main()
{
foo() = "test"; // what does this line do
cout << str << endl;
char c;
cin>>c;
return 0;
}
它确实生成了一些汇编指令,但我不知道它们是做什么的
getString() = "test"; // what does this line do
00007FF68B0D6F1B lea rcx,[rbp+0E8h]
00007FF68B0D6F22 call getString (07FF68B0D1640h)
00007FF68B0D6F27 mov qword ptr [rbp+118h],rax
00007FF68B0D6F2E mov rax,qword ptr [rbp+118h]
00007FF68B0D6F35 mov qword ptr [rbp+120h],rax
00007FF68B0D6F3C lea rdx,[string "test" (07FF68B0E1584h)]
00007FF68B0D6F43 mov rcx,qword ptr [rbp+120h]
00007FF68B0D6F4A call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator= (07FF68B0D1037h)
00007FF68B0D6F4F nop
00007FF68B0D6F50 lea rcx,[rbp+0E8h]
00007FF68B0D6F57 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF68B0D1140h)
cout << str << endl;
本质上,它没有做任何有用的事情。
foo
函数返回字符串str
的副本,并分配给该副本。类似于:
{
string temp;
temp = foo();
temp = "test";
// Here the temp object is destructed, and the modifications
// made to it are lost
}
因为该语句没有任何可观察到的效果,所以"好像"规则不仅允许编译器跳过赋值,还允许编译器跳过对foo
本身的调用。
如果foo
函数向str
对象返回引用,情况将大不相同:
string& foo() {
return str;
}
因为这样分配会分配给实际的str
对象:
{
string& temp_ref = foo();
temp_ref = "test"; // Really assigns to str
}
foo()
返回str
的副本。
foo() = "test";
这一行将副本的内容更改为";测试";但不会将其存储在任何地方,因此它实际上什么都不做。