这段代码是否有效(和定义的行为)?
int &nullReference = *(int*)0;
Run Code Online (Sandbox Code Playgroud)
这两个g ++以及铛++编译它没有任何警告,即使使用-Wall
,-Wextra
,-std=c++98
,-pedantic
,-Weffc++
...
当然,引用实际上不是null,因为它无法访问(这意味着取消引用空指针),但我们可以通过检查其地址来检查它是否为null:
if( & nullReference == 0 ) // null reference
Run Code Online (Sandbox Code Playgroud) 我对这个程序有一些疑问:
#include <iostream>
#include <type_traits>
#include <functional>
using namespace std;
template <typename T> void foo ( T x )
{
auto r=ref(x);
cout<<boolalpha;
cout<<is_same<T&,decltype(r)>::value;
}
int main()
{
int x=5;
foo (x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
false
Run Code Online (Sandbox Code Playgroud)
我想知道,如果std::ref
没有返回对象的引用,那么它会做什么?基本上,有什么区别:
T x;
auto r = ref(x);
Run Code Online (Sandbox Code Playgroud)
和
T x;
T &y = x;
Run Code Online (Sandbox Code Playgroud)
另外,我想知道为什么存在这种差异?为什么我们需要std::ref
或std::reference_wrapper
什么时候有参考(即T&
)?
最近提出了C++核心指南(恭喜!),我担心gsl::not_null
类型.如I.12中所述:声明一个不能为null的指针not_null
:
帮助避免解除引用nullptr错误.通过避免对nullptr进行冗余检查来提高性能.
...
通过声明源代码中的意图,实现者和工具可以提供更好的诊断,例如通过静态分析查找某些类错误,并执行优化,例如删除分支和空测试.
目的很明确.但是,我们已经有了语言功能.不能为null的指针称为引用.虽然引用一旦创建就无法反弹,但这个问题可以解决std::reference_wrapper
.
我gsl::not_null
和之间的主要区别在于,std::reference_wrapper
后者只能用于代替指针,而前者适用于任何事物 - 可nullptr
分配(引自 F.17:使用not_null来表示"null"不是有效值):
not_null
不只是内置指针.它的工作原理为array_view
,string_view
,unique_ptr
,shared_ptr
,和其他类似指针的类型.
我想象功能比较表如下:
T&
:
nullptr
?- 是的std::reference_wrapper<T>
:
nullptr
?- 是的gsl::not_null<T*>
:
nullptr
?- 是的现在这里是问题,最后:
std::reference_wrapper
现在没用了?PS我创建了标签cpp-core-guidelines
,guideline-support-library
为此,我希望正确.
template <typename T>
void myswap(T a,T b)
{
T temp = a;
a = b;
b = temp;
}
int main()
{
int m(20),n(30);
myswap(ref(m),ref(n));
//m is still 20 and n is still 30
}
Run Code Online (Sandbox Code Playgroud)
为什么m和n的值没有互换?传递包含在std::ref
INCREMENT函数中的值会导致原始变量(调用INCREMENT函数的堆栈帧中的变量)中的值更改.或者,std::ref
使用受限制/限制?
背景:
我正在尝试实现一个函数,我们称之为它mysort
,它接受可变数量的相同类型的参数并对它们进行排序。例如下面的代码应该打印1 2 3
template <typename ... Args>
void mysort(Args& ... args);
int main(int, char**)
{
int x = 3;
int y = 1;
int z = 2;
mysort(x, y, z);
cout << x << ' ' << y << ' ' << z << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我尝试过的:
这是我想出的解决方案
#include <array>
#include <algorithm>
#include <functional>
template <typename T, typename ... Args>
void mysort(T& t, Args& ... args)
{
constexpr size_t n = sizeof...(Args) + 1; …
Run Code Online (Sandbox Code Playgroud) 所以我std::reference_wrapper
在 C++11 中发现了这个奇特的东西,我发现它在未来的程序开发中可能很有用。我玩了一会儿,我认为它可以在某些情况下取代旧的参考以获得更好的使用,直到我遇到以下错误:
#include <iostream>
#include <functional>
class testbench {
public:
int ownerid = 5;
bool camper = false;
};
class testing {
public:
testing(testbench &x);
int quack = 3;
std::reference_wrapper <testbench> camper;
};
testing::testing(testbench &x):camper(x) {
}
int main() {
testbench tempo;
testing test_a (tempo);
std::cout << test_a.camper.ownerid;
}
Run Code Online (Sandbox Code Playgroud)
这会导致 gcc 中出现错误(我使用 Code::Blocks 作为编辑器,使用 gcc 作为编译器)
'class std::reference_wrapper<testbench>' has no member named 'ownerid'
Run Code Online (Sandbox Code Playgroud)
如果线
std::reference_wrapper <testbench> camper;
Run Code Online (Sandbox Code Playgroud)
更改为:
testbench &camper;
Run Code Online (Sandbox Code Playgroud)
然后一切都按照我的预期进行。
我该如何解决这个问题,或者这只是我 std::reference_wrapper
作为参考的一般改进的误解?
我想知道将变量作为类的引用传递的最佳方法是什么。据我所知,有三种方法(也许更多,因为我了解 C++)。
\n给出以下示例:
\n#include <string>\n#include <iostream>\n\nclass Database {\n public:\n std::string name;\n};\n\nclass ConsumeDatabase1 {\n public:\n ConsumeDatabase1(Database& database) : database_{database} {\n std::cout << &database << "\\n";\n }\n private:\n Database& database_;\n};\n\nclass ConsumeDatabase2 {\n public:\n ConsumeDatabase2(Database* database): database_{database} {\n std::cout << database << "\\n";\n }\n\n private:\n Database* database_;\n};\n\nclass ConsumeDatabase3 {\n public:\n ConsumeDatabase3(Database& database): database_{&database} {\n std::cout << &database << "\\n";\n }\n\n private:\n Database* database_;\n};\n\nint main() {\n Database db;\n db.name = "Test";\n\n ConsumeDatabase1 db1{db};\n ConsumeDatabase2 db2{&db};\n ConsumeDatabase3 db3{db};\n}\n
Run Code Online (Sandbox Code Playgroud)\n版本一和第二版之间的区别在于,在版本一中我不能(那么容易)通过a,nullptr
而在版本二中可以允许,对吗?
我尝试使用以下struct
声明编写程序:
struct N
{
int value;
N Left;
N Right;
};
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我的程序中会有无数个结构.我仍然希望我的左派和右派拥有与N完全相同的结构.有没有办法做到这一点?