标签: reference-binding

C ++-使用const引用来延长临时成员,确定成员或UB成员?

考虑这样的事情:

#include <iostream>

struct C {
    C(double x=0, double y=0): x(x) , y(y) {
        std::cout << "C ctor " << x << " " <<y << " "  << "\n";
    }
    double x, y;
};

struct B {
    B(double x=0, double y=0): x(x), y(y) {}
    double x, y;
};

struct A {
    B b[12];

    A() {
        b[2] = B(2.5, 14);
        b[4] = B(56.32,11.99);
    }
};


int main() {
    const B& b = A().b[4];
    C c(b.x, b.y);
}
Run Code Online (Sandbox Code Playgroud)

当我用-O0编译时,我得到了打印

C ctor …
Run Code Online (Sandbox Code Playgroud)

c++ temporary lifetime language-lawyer reference-binding

37
推荐指数
1
解决办法
1072
查看次数

是否可以通过const引用返回默认参数的值?

是否可以通过const引用返回默认参数的值,如以下示例所示:

https://coliru.stacked-crooked.com/a/ff76e060a007723b

#include <string>

const std::string& foo(const std::string& s = std::string(""))
{
    return s;
}

int main()
{
    const std::string& s1 = foo();
    std::string s2 = foo();

    const std::string& s3 = foo("s");
    std::string s4 = foo("s");
}
Run Code Online (Sandbox Code Playgroud)

c++ object-lifetime language-lawyer default-arguments reference-binding

27
推荐指数
3
解决办法
662
查看次数

在引用初始化中使用已删除的复制构造函数复制初始化

考虑以下代码:

#include <iostream>
class Data{
public:
    Data() = default;
    Data(Data const&) = delete;
    Data(int) {

    }
};
int main(){
  int a = 0;
  const std::string& rs = "abc"; // rs refers to temporary copy-initialized from char array
  Data const& d_rf = a;          // #2 but here can be complied
  // accroding to the standard, the reference in #2 is bound to a temporary object, the temporary is copy-initialized from the expression
}
Run Code Online (Sandbox Code Playgroud)

[dcl.init.ref]

如果T1或T2是一个类类型和T1不参考相关到T2,用户定义的转换正在使用的规则考虑复制初始化型“CV1 T1”的对象的由用户定义的转换([dcl.init ], [over.match.copy], [over.match.conv]); …

c++ language-lawyer implicit-conversion c++11 reference-binding

19
推荐指数
1
解决办法
1403
查看次数

这个C++静态分析规则是否有意义?

我正在实现一些C++静态分析规则,其中一个规则禁止函数返回引用或指向函数引用参数的指针,即以下都是不兼容的:

int *f(int& x) { return &x; } // #1
const int *g(const int& x) { return &x; } // #2
int& h(int& x) { return x; } // #3
const int& m(const int& x) { return x; } // #4
Run Code Online (Sandbox Code Playgroud)

为此给出的理由是"它是实现定义的行为,无论引用参数是临时对象还是对参数的引用."

然而,我对此感到困惑,因为C++中的流操作符是以这种方式编写的,例如

std::ostream& operator<<(std::ostream& os, const X& x) {
    //...
    return os;
}
Run Code Online (Sandbox Code Playgroud)

我认为我非常有信心C++中的流操作符通常不会表现出实现定义的行为,所以发生了什么?

根据我目前的理解,我希望#1和#3能够很好地定义,因为temporaries不能绑定到非const引用,所以int& x指的是一个超出范围的实际对象函数,因此返回指向该对象的指针或引用是好的.我希望#2变得狡猾,因为一个临时的本来可以被束缚const int& x,在这种情况下,试图取其地址似乎是一个糟糕的计划.我不确定#4 - 我的直觉是,这也可能是狡猾的,但我不确定.特别是,我不清楚以下情况会发生什么:

const int& m(const int& x) { return x; }
//...
const int& r = m(23);
Run Code Online (Sandbox Code Playgroud)

c++ reference language-lawyer reference-binding

12
推荐指数
1
解决办法
315
查看次数

const引用是否绑定到另一个引用,该引用是从临时的悬空引用转换而来的?

以下是代码段:

#include <iostream>
using namespace std;
struct B{
     int b;
     ~B(){cout <<"destruct B" << endl;}
};
B func(){
    B b;
    b.b = 1;
    return b;
}
int main(){
    const B& instance = (const B&)func(); //is `instance` a dangling reference?
    cout <<instance.b<<endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这个在线编译器中的输出是

destruct B
destruct B
1
Run Code Online (Sandbox Code Playgroud)

因此返回值似乎比cout操作早破坏.所以这instance似乎是一个悬垂的参考.

如果我们const B& instance = (const B&)func();改为 const B& instance =func();,那么结果是

destruct B
1
destruct B
Run Code Online (Sandbox Code Playgroud)

作为补充,如果我在vs2015中测试代码,那么输出是最后一个.但是,如果在gcc(4.6之前)中进行测试,则输出为前者,但后者为4.6之后的版本.所以我想知道在线编译器是错误的还是引用实际上是悬空的.

c++ object-lifetime language-lawyer reference-binding

10
推荐指数
1
解决办法
189
查看次数

为参考参数和优化更改创建临时对象

我有以下代码

#include <iostream>

void foo(const int* const &i_p) {
    std::cout << &i_p << std::endl;
}

int main () {

    int i = 10;
    int* i_p = &i;
    std::cout << &i_p << std::endl;
    foo(i_p);
}
Run Code Online (Sandbox Code Playgroud)

x86-64 clang 9.0.0输出上是

Program returned: 0
0x7ffc43de63f8
0x7ffc43de6400
Run Code Online (Sandbox Code Playgroud)

x86-64 clang 10.0.0 而在编译器资源管理器链接上,输出变为

Program returned: 0
0x7ffc9da01ef0
0x7ffc9da01ef0
Run Code Online (Sandbox Code Playgroud)

这里进行了什么优化来提供相同的地址?我相信应该实现一个临时对象,因为我们无法将低级const指针绑定到低级non-const

c++ const-correctness language-lawyer clang++ reference-binding

6
推荐指数
1
解决办法
93
查看次数

可以将 const T*&amp;&amp; 绑定到 T* 类型的 xvalue 吗?

考虑以下代码:(https://godbolt.org/z/8W699x6q6

int* p;
const int*&& r = static_cast<int*&&>(p);
Run Code Online (Sandbox Code Playgroud)

注意:const int*&&是指向 的指针的右值引用const int

Clang 编译它,并r绑定到一个临时对象:

p: .quad   0
r: .quad   _ZGR1r_ // r is a reference to a temporary object, otherwise this would be p
Run Code Online (Sandbox Code Playgroud)

GCC 拒绝此代码:

<source>:2:18: error: binding reference of type 'const int*&&' to 'int*' discards qualifiers
    2 | const int *&&r = static_cast<int*&&>(p);
      |                  ^~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

就我个人而言,我认为 GCC 正确地实现了CWG 2352[dcl.init.ref] p4的更改,但我不确定我的解释是否正确。这里哪个编译器是正确的?


注意:本问题中的示例受到CWG 2018中提到的最后一行代码的启发。

注意:如果允许绑定const int*&& …

c++ const-correctness language-lawyer temporary-objects reference-binding

6
推荐指数
1
解决办法
269
查看次数

如果没有const引用,是否会删除临时对象?

让我们来看看这两个功能:

std::string get_string()
{
    std::string ret_value;
    // Calculate ret_value ...
    return ret_value;
}

void process_c_string(const char* s)
{
    std::cout << s << endl;
}
Run Code Online (Sandbox Code Playgroud)

这里有两个可能的process_c_string带有参数的调用get_string.

  1. 没有绑定const引用的返回对象get_string.

    process_c_string(get_string().c_str());
    
    Run Code Online (Sandbox Code Playgroud)
  2. 用绑定const引用返回的对象get_string.

    const std::string& tmp_str = get_string();
    process_c_string(tmp_str.c_str());
    
    Run Code Online (Sandbox Code Playgroud)

我知道第二种方式是有效的,但第一种方式是什么,标准对此案例有什么看法呢?返回的临时对象是否get_string会在process_c_str完成之前删除,因为没有const reference它?

注意:这两个版本在MSVC中都可以.

c++ temporary const-reference reference-binding

5
推荐指数
1
解决办法
224
查看次数

Shared_ptr&lt;T&gt; 到 const shared_ptr&lt;const T&gt;&amp;

我对shared_ptr感到困惑,我的主要问题是:当我执行以下操作时,c ++是否创建一个新对象(shared_ptr对象)?

void Func1(const shared_ptr<T>& rhs) {}
void Func2(const shared_ptr<const T>& rhs) {}
shared_ptr<T> v1;
Func1(v1);
Func2(v1);
Run Code Online (Sandbox Code Playgroud)

显然,Func1(v1)是通过 ref 传递的。然而,又如何呢Func2(v1)

编译者会在后面做以下事情吗?

shared_ptr<const T> tmp_v2 = v1;
Func2(tmp_v2);
Run Code Online (Sandbox Code Playgroud)

我关心它,因为Func2可能比Func1.

非常感谢您的帮助!

shared-ptr implicit-conversion c++11 pass-by-const-reference reference-binding

5
推荐指数
1
解决办法
2054
查看次数

为什么将double转换为看似任何原语的const引用?

考虑以下代码:

#include <iostream>

float func(char const & val1, unsigned int const & val2)
{
    return val1 + val2;
}

int main() {
    double test1 = 0.2;
    double test2 = 0.3;

    std::cout << func(test1, test2) << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

尽管我将a传递double给采用const引用小于a的类型的函数double(在我的系统上sizeof(double) == 8,while sizeof(unsigned int) == 4sizeof(char) == 1按定义),但该函数仍可编译和运行。如果引用不是const,则编译失败(例如, float func(char & val1, unsigned int & val2)而不是当前定义),并显示以下错误:

不能将'char&'类型的非常量左值引用绑定到'char'类型的右值

在Godbolt上使用GCC,Clang,ICC和MSVC进行测试时,我得到的行为完全相同,因此它看起来是标准的。导致该接受的const-references是什么呢,而引用不是?另外,我曾经使用过-Wall -pedantic-为什么我没有收到有关转换范围缩小的警告?当函数按值传递而不是按引用传递时...

c++ language-lawyer reference-binding

4
推荐指数
1
解决办法
225
查看次数