C++只允许将临时对象分配给const引用.它不允许分配临时对象来引用.
例如:
String& a = String("test"); // Error
const String& a = String("test"); // Ok
Run Code Online (Sandbox Code Playgroud)
无论我到哪里谷歌这个结果,我只看到以下答案
有人说,临时对象在声明后消失了.所以你不应该修改它.
如果C++,如此热衷于阻止修改临时对象,它应该阻止读取临时对象吗?如果临时对象消失了,那么从那里读取内容是没有意义的吗?权利可能发生的可能情况也可能涉及阅读.
那为什么它一直阻止写入并允许读取?
请给我一个可靠的c ++代码说明.
请不要通过指出一些替代方案来偏离问题.请给我一个可靠的答案代码,为什么const int&被允许,而int&不允许用于临时对象.
一个说&&在那里..我的问题不同..另一个说,改变不会反映..改变也不会反映即使它也是const int&.例如:双倍; Const int&i = a; 一个++; 不会影响我..
在下面的简单示例中,为什么不能ref2绑定到结果min(x,y+1)?
#include <cstdio>
template< typename T > const T& min(const T& a, const T& b){ return a < b ? a : b ; }
int main(){
int x = 10, y = 2;
const int& ref = min(x,y); //OK
const int& ref2 = min(x,y+1); //NOT OK, WHY?
return ref2; // Compiles to return 0
}
Run Code Online (Sandbox Code Playgroud)
现场示例 -产生:
main:
xor eax, eax
ret
Run Code Online (Sandbox Code Playgroud)
编辑: 我认为以下示例更好地描述了一种情况。
#include <stdio.h>
template< typename T >
constexpr T const& min( T …Run Code Online (Sandbox Code Playgroud) 在Eckel,第1卷,第367页
//: C08:ConstReturnValues.cpp
// Constant return by value
// Result cannot be used as an lvalue
class X {
int i;
public:
X(int ii = 0);
void modify();
};
X::X(int ii) { i = ii; }
void X::modify() { i++; }
X f5() {
return X();
}
const X f6() {
return X();
}
void f7(X& x) { // Pass by non-const reference
x.modify();
}
int main() {
f5() = X(1); // OK -- non-const return value
f5().modify(); // OK …Run Code Online (Sandbox Code Playgroud) 我的一个朋友给我看了一个 C++20 程序:
#include <iostream>
struct A
{
A() {std::cout << "A()\n";}
~A() {std::cout << "~A()\n";}
};
struct B
{
const A &a;
};
int main()
{
B x({});
std::cout << "---\n";
B y{{}};
std::cout << "---\n";
B z{A{}};
std::cout << "---\n";
}
Run Code Online (Sandbox Code Playgroud)
在 GCC 中,它打印:
A()
~A()
---
A()
---
A()
---
~A()
~A()
Run Code Online (Sandbox Code Playgroud)
https://gcc.godbolt.org/z/ce3M3dPeo
因此,A在 y 和 z 情况下,的寿命会延长。
在 Visual Studio 中,结果是不同的:
A()
~A()
---
A()
---
A()
~A()
---
~A()
Run Code Online (Sandbox Code Playgroud)
所以A只有在 y …
考虑以下程序:
#include <iostream>
int const * f(int const &i)
{
return &i;
}
int main()
{
std::cout << f(42); // #1
std::cout << f(42); // #2
std::cout << f(42) << f(42); // #3
}
Run Code Online (Sandbox Code Playgroud)
根据编译器和设置的优化级别,打印在行上的地址可能彼此不同#1,#2也可能不同。
但是,无论选择何种编译器或优化级别,行#3中打印的 2 个地址总是彼此不同。
这是一个可以玩的演示。
那么f在每种情况下返回什么的规则是什么?
我在编译一些可移植代码时碰到了这个gcc.基本上这个奇怪的代码在Visual Studio中编译,这真的让我大吃一惊:
class Zebra {int x;};
Zebra goo() {Zebra z; return z;}
void foo(Zebra &x)
{
Zebra y;
x = y;
foo(goo());
}
Run Code Online (Sandbox Code Playgroud)
Visual studio让这一个飞.gcc将捕获此作为编译错误.有趣的是,如果你输入def Zebra为int,VC++会抱怨.相当矛盾的行为.思考?
我使用了以下语法糖:
for (auto& numberString: {"one", "two", "three", "four"}) { /* ... */}
Run Code Online (Sandbox Code Playgroud)
这是有效的代码吗?AFAIK,基于这个问题,这应该是非法的,但代码按预期运行。我认为我对此事的理解不正确。
据我所知,只有文字不应该有内存地址,但链接的问题正在讨论临时值和右值。
我最近通过Herb Sutter获得了"Exceptional C++",我对他在第6项 - 临时对象中提出的特别建议表示严重怀疑.
他提供了在以下代码中查找不必要的临时对象:
string FindAddr(list<Employee> emps, string name)
{
for (list<Employee>::iterator i = emps.begin(); i != emps.end(); i++)
{
if( *i == name )
{
return i->addr;
}
}
return "";
}
Run Code Online (Sandbox Code Playgroud)
作为示例之一,他建议预先计算emps.end()循环之前的值,因为每次迭代都会创建一个临时对象:
对于大多数容器(包括列表),调用end()返回一个必须构造和销毁的临时对象.因为值不会改变,所以在每次循环迭代中重新计算(并重建和重新描述)它都是不必要的低效和不美观的.该值应仅计算一次,存储在本地对象中,然后重复使用.
他建议用以下内容代替:
list<Employee>::const_iterator end(emps.end());
for (list<Employee>::const_iterator i = emps.begin(); i != end; ++i)
Run Code Online (Sandbox Code Playgroud)
对我来说,这是不必要的并发症.即使用compact替换丑陋的类型声明auto,他仍然会获得两行代码而不是一行代码.更重要的是,他end在外部范围内有这个变量.
我确信现代编译器无论如何都会优化这段代码,因为我实际上const_iterator在这里使用并且很容易检查循环内容是否以某种方式访问容器.编译器在过去的13年里变得更聪明,对吧?
无论如何,i != emps.end()在大多数情况下,我更喜欢第一个版本,我不太担心性能.但我想知道,这是否是一种我可以依靠编译器进行优化的结构?
更新
感谢您就如何更好地制作这些无用的代码提出建议.请注意,我的问题是关于编译器,而不是编程技术.现在唯一相关的答案来自NPE和Ellioh.
下面的 C++ 代码格式正确吗?std::string函数执行完成之前还是之后会被销毁?
void my_function(const char*);
...
my_function(std::string("Something").c_str());
Run Code Online (Sandbox Code Playgroud)
我知道我可以做到my_function("Something"),但我用std::string这种方式来说明我的观点。
我知道为一个const左值引用分配一个rvalue会延长临时值的生命周期,直到范围结束.但是,我不清楚何时使用它以及何时依赖返回值优化.
LargeObject lofactory( ... ) {
// construct a LargeObject in a way that is OK for RVO/NRVO
}
int main() {
const LargeObject& mylo1 = lofactory( ... ); // using const&
LargeObject mylo2 = lofactory( ... ); // same as above because of RVO/NRVO ?
}
Run Code Online (Sandbox Code Playgroud)
根据Scot Meyers的"更有效的C++"(第20项),编译器可以优化第二种方法来构建适当的对象(这将是理想的,并且正是人们试图用const&第一种方法实现的).
const&临时工具以及何时依赖RVO/NRVO?const&方法比不使用该方法更糟糕的情况?(我正在考虑关于C++ 11移动语义的例子,如果LargeObject实现了那些......)c++ optimization const-reference temporary-objects return-value-optimization
c++ ×10
c++11 ×1
c++17 ×1
c++20 ×1
optimization ×1
performance ×1
pointers ×1
reference ×1
stl ×1
string ×1