考虑这样的事情:
#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) 是否可以通过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
考虑以下代码:
#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)
如果T1或T2是一个类类型和T1不参考相关到T2,用户定义的转换正在使用的规则考虑复制初始化型“CV1 T1”的对象的由用户定义的转换([dcl.init ], [over.match.copy], [over.match.conv]); …
c++ language-lawyer implicit-conversion c++11 reference-binding
我正在实现一些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) 以下是代码段:
#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之后的版本.所以我想知道在线编译器是错误的还是引用实际上是悬空的.
我有以下代码
#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
考虑以下代码:(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
让我们来看看这两个功能:
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.
没有绑定const引用的返回对象get_string.
process_c_string(get_string().c_str());
Run Code Online (Sandbox Code Playgroud)用绑定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中都可以.
我对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
考虑以下代码:
#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) == 4和sizeof(char) == 1按定义),但该函数仍可编译和运行。如果引用不是const,则编译失败(例如, float func(char & val1, unsigned int & val2)而不是当前定义),并显示以下错误:
不能将'char&'类型的非常量左值引用绑定到'char'类型的右值
在Godbolt上使用GCC,Clang,ICC和MSVC进行测试时,我得到的行为完全相同,因此它看起来是标准的。导致该接受的const-references是什么呢,而引用不是?另外,我曾经使用过-Wall -pedantic-为什么我没有收到有关转换范围缩小的警告?当函数按值传递而不是按引用传递时...