Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 不应该';NRVO保证本地命名变量和调用站点变量采用相同的地址吗?_C++_Nrvo - Fatal编程技术网

C++ 不应该';NRVO保证本地命名变量和调用站点变量采用相同的地址吗?

C++ 不应该';NRVO保证本地命名变量和调用站点变量采用相同的地址吗?,c++,nrvo,C++,Nrvo,我认为应该,因为这对正确性很重要。然而,我对Clang的输出感到惊讶。考虑下面的代码: #include <iostream> struct S { int i; S(int i) : i(i) {} S(S&&) { std::cout << "S(S&&)\n"; } S(S const&) = delete; }; S f() { S s{42}

我认为应该,因为这对正确性很重要。然而,我对Clang的输出感到惊讶。考虑下面的代码:

#include <iostream>

struct S
{
    int i;

    S(int i) : i(i) {}

    S(S&&)
    {
        std::cout << "S(S&&)\n";
    }

    S(S const&) = delete;
};

S f()
{
    S s{42};
    std::cout << &s << "\n";
    return s;
}

int main()
{
    S s{f()};
    std::cout << &s << "\n";
    std::cout << s.i << "\n";
}
应用了NRVO,并且它们采用了预期的相同地址

然而,克朗:

已应用NRVO,但地址不同

如果您想知道为什么拥有相同的地址很重要,这是因为某些对象可能会在构建时使用其地址进行一些注册,并且如果对象被移动,则应通知它(例如,通过移动ctor)

应用了NRVO,但具有不同的内存地址,因此使其格式不正确。 这显然违反了合同-没有调用自定义移动/复制ctor,编译器如何将s的数据“复制”到其他地方

这是叮当作响的虫子吗


如果我们将析构函数添加到
S
,例如

~S() {}

,Clang输出相同的地址。

显然是Clang中的一个bug,它们应该是相同的,否则下面的内容将是错误的

struct S
{
    int i;
    int* ptr;

    S(int i) : i(i) {
        this->ptr = &this->i;
    }

    S(S&& s)
    {
        this->i = s.i; 
        this->ptr = &this->i;
        std::cout << "S(S&&)\n";
    }

    S(S const&) = delete;
};
结构
{
int i;
int*ptr;
S(int i):i(i){
此->ptr=&此->i;
}
S(S&S)
{
这个->i=s.i;
此->ptr=&此->i;

std::cout@Still.用这种想法回答了这个问题,他们真的应该是电子邮件链的起点。这是Clang完全实现的安腾ABI规范中的一个错误。是的。只有当
sizeof(S)好的,ABI传递规则将“NRVO vs.复制/移动”联系在一起时才会这样做对非平凡析构函数的行为…但是当已经做出了有利于复制/移动(re:Clang)的决定时,哪个ABI规则允许复制而不调用任何构造函数?在这种情况下,Clang使用了什么复制机制?ABI对此怎么说?
~S() {}
struct S
{
    int i;
    int* ptr;

    S(int i) : i(i) {
        this->ptr = &this->i;
    }

    S(S&& s)
    {
        this->i = s.i; 
        this->ptr = &this->i;
        std::cout << "S(S&&)\n";
    }

    S(S const&) = delete;
};