问题描述
我正在使用以下代码进行一些测试:
#include <iostream>
#include <string>
using namespace std;
string& changeSomething(string&& s) {
s[0] = 'a';
return s;
}
int main() {
string s = changeSomething("hello");
cout << s << endl;
}
这里我将一个右值引用传递给函数,并返回一个对对象的引用。这里的问题是我认为这会给 UB,因为我将 r 值传递给函数并且它没有分配内存地址,但是输出:
你好
这里有我遗漏的东西吗?
解决方法
这不是UB。临时对象直到表达式结束才会被销毁,您可以在同一表达式中复制它。要获得基本的第一个想法,您可以使用 -fsanitize=address -fsanitize=undefined
。它并不完美,但有帮助。为了更准确地了解何时调用构造函数/析构函数,您可以从中打印一些内容:
#include <cstdio>
struct Noisy {
char const* data;
Noisy(char const* ch) : data{ch} { std::puts("Noisy()"); }
Noisy(Noisy const& oth) : data{oth.data} { std::puts("Noisy(Noisy const&)"); }
~Noisy() { std::puts("~Noisy()"); }
};
Noisy& changeSomething(Noisy&& s) { return s; }
int main() {
Noisy s = changeSomething("Hello");
std::puts(s.data);
}
输出为:
Noisy()
Noisy(Noisy const&)
~Noisy()
Hello
~Noisy()
可以看到复制是在销毁前完成的,所以销毁后什么也访问不了。在 Compiler Explorer 上查看。