首页 > 解决方案 > 了解这种行为(r 值参考)

问题描述

我正在使用以下代码进行一些测试:

#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 值传递给函数并且它没有分配内存地址,但这会输出:

艾洛

有什么我在这里想念的吗?

标签: c++visual-studioc++11

解决方案


这不是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上查看。


推荐阅读