#include <iostream>
using namespace std;
struct CL
{
CL()
{
cout<<"CL()"<<endl;
}
CL(const CL&)
{
cout<<"CL(const CL&)"<<endl;
}
~CL()
{
cout<<"~CL()"<<endl;
}
};
CL cl;
CL fnc()
{
return cl;
}
int main() {
cout<<"start"<<endl;
const CL& ref=static_cast<const CL&>(fnc());
//...Is "ref" valid here??
cout<<"end"<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
fnc()返回的临时对象的生命周期是多少?它是"ref"或临时引用static_cast(fnc())的生命周期,它在语句结束时被销毁了吗?
gcc的输出(fnc()的生命周期是"ref"的生命周期):
CL() //global object "cl"
start
CL(const CL&)
end
~CL()
~CL() //global object "cl"
Run Code Online (Sandbox Code Playgroud)
VS2013的输出(fnc()的寿命是临时参考的寿命):
CL() //global object "cl"
start
CL(const CL&)
~CL()
end
~CL() //global object "cl"
Run Code Online (Sandbox Code Playgroud)
标准是什么?
该代码可以编译吗?
#include <iostream>
template <typename T>
struct TMPL
{
using TP = typename T::TP; //is CL::TP visible (with T == CL)?
};
struct CL
{
using TP = int;
TMPL<CL>::TP val;
};
int main()
{
CL cl;
}
Run Code Online (Sandbox Code Playgroud)
根据标准14.6.4.1/4,在CL类定义之前立即实例化TMPL
对于类模板专业化,...,如果专业化隐式实例化,因为它是从另一个模板特内引用,...... 否则,实例化的这样一个专业化的点后面紧跟的命名空间范围声明或定义,是指专业化.
因此,CL :: TP在TMPL实例化点中不可见,但所有编译器(MSVC,gcc,clang)都编译得很好.我还发现了一份缺陷报告http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287,但显然未被接受
我正在阅读 Nicolai Josuttis 的《C++ 17 Completed Guide》,并遇到了以下表达式:
foo(arg1), (foo(arg2), foo(arg3));
Run Code Online (Sandbox Code Playgroud)
作者声称,内置逗号运算符的求值顺序将从左到右,但可以通过重载它们来更改。但是,我看到了有关 cppreference 的“求值顺序”文章(https://en.cppreference.com/w/cpp/language/eval_order)并发现了以下声明:
- 内置逗号运算符的第一个(左)参数的每个值计算和副作用都在第二个(右)参数的每个值计算和副作用之前排序。
和
- 当使用运算符表示法调用时,每个重载运算符都遵守其重载的内置运算符的排序规则。
因此,根据语句 16,cppreference 似乎声称重载的逗号运算符与其内置对应项具有相同的求值顺序。那么,作者所说的“通过重载逗号运算符,您可以更改其求值顺序”到底是什么意思,以及预期的行为到底是什么?
以下 constexpr 函数无法编译:
constexpr void fnc()
{
constexpr int i = 5;
constexpr auto ptr = &i;
}
Run Code Online (Sandbox Code Playgroud)
ptr考虑到所有计算都发生在 constexpr 函数中并且无需声明 constexpr 即可工作,为什么不能是ptrconstexpr?
为什么CL实例转换为const int&模糊不清?
struct CL
{
operator const int&()
{
}
operator int&()
{
}
};
void fnc(const int&)
{
}
int main()
{
CL cl;
fnc(cl);
}
Run Code Online (Sandbox Code Playgroud)
有两种方法:
1).cl.operator const int&()导致用户定义的转换
2).cl.operator int&()导致用户定义的转换,然后进行资格转换(int&到const int&)
第一种方式比第二种方式更好,不是吗?我看到标准,但什么也没找到.
#include <iostream>
#include <string>
void fnc (const std::string&)
{
std::cout<<1;
}
void fnc (std::string&&)
{
std::cout<<2;
}
int main()
{
fnc ("abc");
}
Run Code Online (Sandbox Code Playgroud)
所有的编译器选择std::string&&版本fnc,并且它是合乎逻辑的,因为临时std::string是为引用绑定创建的,但我找不到,它在C++ 14 Standard中描述了什么.我在那里发现了一个段落(3.2):
- 标准转换序列S1是比标准转换序列S2更好的转换序列
[...]
- S1和S2是引用绑定(8.5.3),并且都不引用没有ref-qualifier声明的非静态成员函数的隐式对象参数,S1将rvalue引用绑定到rvalue ,S2绑定左值引用
但事实并非如此,因为S1将一个右值引用绑定到一个左值("abc",即const char [4]的左值).我在哪里可以找到描述,选择第二个过载?
PS我指的是C++ 14 Standard而不是C++ 11,因为我知道,C++ 11中存在一些与rvalue引用绑定相关联的缺陷报告.
如何通过文本在QTreeWidgetItem中查找项目?是否有QTreeWidget的findItem方法的类比?
我不明白为什么不正确
#include <iostream>
using namespace std;
struct CL{};
template <typename T>
void fnc(T t)
{
f(t);
}
namespace NS {
void f(CL){}
void fn() {fnc(CL()); /*error is here*/}
//point of instantiation fnc<CL> is here (in namespace scope,
//according to 14.6.4.1/1)
}
int main(){}
Run Code Online (Sandbox Code Playgroud)
调用f(t)模板函数fnc取决于模板参数,然后名称查找必须位于实例化点.我看到标准(C++ 14)14.6.4.1/1
对于函数模板特化,成员函数模板特化,或成员函数或类模板的静态数据成员的特化,如果特化是隐式实例化的,因为它是从另一个模板特化和其中的上下文中引用的引用依赖于模板参数,专门化的实例化点是封闭专门化的实例化点.否则,这种特化的实例化点紧跟在引用特化的命名空间范围声明或定义之后.
f(CL)在实例化时可见fnc<CL>,但所有编译器(VS,gcc,clang)都会出错.这种行为的原因是什么?
根据当前标准 (20.7.9),std::allocator有一个成员propagate_on_container_move_assignment设置为true_type:
模板类分配器
{
public:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* 指针;
typedef const T* const_pointer;
typedef T&参考;
typedef const T& const_reference;
typedef T value_type;
模板结构重新绑定 { typedef 分配器其他;};
typedef true_typepropagate_on_container_move_assignment;
typedef true_type is_always_equal;
[...]
std::allocator没有数据成员,并且总是与任何其他std::allocator. 是否有任何理由在移动分配时移动这些默认分配器?
我知道线程安全单例的常见实现如下所示:
Singleton* Singleton::instance() {
if (pInstance == 0) {
Lock lock;
if (pInstance == 0) {
Singleton* temp = new Singleton; // initialize to temp
pInstance = temp; // assign temp to pInstance
}
}
return pInstance;
}
Run Code Online (Sandbox Code Playgroud)
但为什么他们说这是一个线程安全的实现呢?
例如,第一个线程可以通过 上的两个测试pInstance == 0,创建new Singleton并将其分配给temp指针,然后开始分配pInstance = temp(据我所知,指针分配操作不是原子的)。
同时,第二个线程测试第一个线程pInstance == 0,其中pInstance仅分配了一半。它不是 nullptr,但也不是一个有效的指针,然后从函数返回。这样的情况会发生吗?我在任何地方都没有找到答案,似乎这是一个非常正确的实现,但我什么也不明白