为什么Visual C++编译器在这里调用错误的重载?
我有一个ostream的子类,我用它来定义格式化的缓冲区.有时我想创建一个临时的,并立即插入一个字符串,使用通常的<<运算符,如下所示:
M2Stream() << "the string";
Run Code Online (Sandbox Code Playgroud)
不幸的是,程序调用运算符<<(ostream,void*)成员重载,而不是运算符<<(ostream,const char*)非成员.
我将下面的示例编写为测试,我在其中定义了自己的M2Stream类来重现问题.
我认为问题是M2Stream()表达式产生一个临时的,这在某种程度上导致编译器更喜欢void*overload.但为什么?事实证明,如果我为非成员重载const M2Stream&做第一个参数,我就会产生歧义.
另一个奇怪的事情是,如果我首先定义一个const char*类型的变量然后调用它而不是文字字符串字符串,它会调用所需的const char*重载,如下所示:
const char *s = "char string variable";
M2Stream() << s;
Run Code Online (Sandbox Code Playgroud)
就好像文字字符串的类型不同于const char*变量!它们不应该是一样的吗?当我使用临时字符串和字符串字符串时,为什么编译器会调用void*重载?
#include "stdafx.h"
#include <iostream>
using namespace std;
class M2Stream
{
public:
M2Stream &operator<<(void *vp)
{
cout << "M2Stream bad operator<<(void *) called with " << (const char *) vp << endl;
return *this;
}
};
/* If I make first arg const M2Stream &os, I get
\tests\t_stream_insertion_op\t_stream_insertion_op.cpp(39) : error C2666: 'M2Stream::operator <<' : …Run Code Online (Sandbox Code Playgroud) 在使用或时,是否有一种方便且功能性(类似with-...)的临时修改环境变量的方法?shell-comandstart-process
提前谢谢,Per
emacs shell temporary environment-variables convenience-methods
const int &ra=3;
Run Code Online (Sandbox Code Playgroud)
正如我所知,制作raconst将延长临时r值的生命周期,在这种情况下为3.这有点令人困惑,因为我知道ra应该有与r值相同的地址,这里是3,但是3是不是一个真正的变量,它没有存储它的存储器.那怎么可能呢?
有什么区别:
const int& ra=a;
Run Code Online (Sandbox Code Playgroud)
和
int& const ra=a;
Run Code Online (Sandbox Code Playgroud)可能重复:
返回指向文字(或常量)字符数组(字符串)的指针?
以下代码是否正确?
const char* state2Str(enum State state)
{
switch (state)
{
case stateStopped: return "START";
case stateRunning: return "RUNNING";
default: return "UNKNOWN";
}
}
printf("State is: %s\n", state2Str(stateRunning));
Run Code Online (Sandbox Code Playgroud)
令我担心的是该函数返回一个指向临时对象的指针.这种返回值的生命周期是多少?语言是C89.
在下面的代码中,为什么第一个调用会解析catchClass(aClass&)并将临时值作为第二个调用中的参数catchClass(const aClassCatcher&)
#include <iostream>
using namespace std;
class aClassCatcher{};
class aClass{
public:
operator aClassCatcher(){
return aClassCatcher();
}
};
void catchClass(aClass&){
cout << __FUNCSIG__ << endl;
}
void catchClass(const aClassCatcher&){
cout << __FUNCSIG__ << endl;
}
int main()
{
aClass aC;
catchClass(aC); // calls catchClass(aClass&)
catchClass(aClass()); // calls catchClass(const aClassCatcher&)
}
Run Code Online (Sandbox Code Playgroud)
这看起来非常简单,但我坚持使用一个简单的插入语句。见下文:
begin work;
CREATE TEMPORARY TABLE IF NOT EXISTS insert_table AS
(
select
r.resource_id
,fr.file_repos_id
,mv.VALUE
from
resources r
join versions v on v.RESOURCE_ID = r.resource_id
join metadata_values mv on mv.resource_id = r.resource_id
join file_repository fr on fr.file_repos_id = v.foreign_id
where
v.version_status = 'C'
and r.RESOURCE_TYPE = 4
and fr.file_title in ('suburbs')
);
insert
into
metadata_values (elem_id,value,resource_type,resource_id,foreign_id,mtvr_id,mett_id)
values
(62,'test',4,insert_table.resource_id,insert_table.file_repos_id,80,4);
rollback work;
Run Code Online (Sandbox Code Playgroud)
在临时表行中fr.file_title in ('suburbs'),实际列表是从其他地方动态拉取的(这是出于演示目的)。我收到以下错误消息:
错误代码:1054。“字段列表”中的未知列“insert_table.resource_id”
现在,我可以在临时表上运行一个选择,它返回正常,只是在更新语句中失败。我正在从 MySQL 工作台运行它。完全不知道这里发生了什么。
我最近对我的代码进行了类型稳定性检查.当我打电话@code_warntype给它时,我得到以下输出:
Variables:
#unused#::IHT.#kw##L0_reg
#temp#@_2::Array{Any,1}
::IHT.#L0_reg
x::Array{Float64,2}
y::Array{Float64,1}
k::Int64
#temp#@_7::Bool
#temp#@_8::Bool
max_iter::Int64
max_step::Int64
quiet::Bool
v::IHT.IHTVariables{Float64,Array{Float64,1}}
tol::Float64
#temp#@_14::Int64
#temp#@_15::Int64
#temp#@_16::Int64
#temp#@_17::Any
###...###
#temp#@_17::Any = (Core.arrayref(#temp#@_2::Array{Any,1},#temp#@_16::Int64)::Any
###...###
v::IHT.IHTVariables{Float64,Array{Float64,1}} = (Core.typeassert)((Core.arrayref)(#temp#@_2::Array{Any,1},(Base.box)(Int64,(Base.add_int)(#temp#@_16::Int64,1)))::Any,IHT.IHTVariables{Float64,Array{Float64,1}})::IHT.IHTVariables{Float64,Array{Float64,1}}
Run Code Online (Sandbox Code Playgroud)
最小的工作示例,使用我的IHT.jl包:
Pkg.clone("https://github.com/klkeys/IHT.jl")
n = 100; p = 250; k = 2;
x = randn(n,p)
b = zeros(p); b[1:k] = randn(k); shuffle!(b)
y = x*b + randn(n)
@code_warntype L0_reg(x, y, k, quiet=true)
Run Code Online (Sandbox Code Playgroud)
看起来编译器正在使用它#temp#来读取函数的参数L0_reg.函数参数已完全指定.这个邪恶的小#temp#@_2变量从哪里出现?我能告诉编译器它的类型是什么吗?(希望不是Array{Any,1}......)
我想测试一个临时对象是否至少与持有const引用的临时对象一样长,所以我想出了这个例子.
#include <iostream>
struct Test {
Test() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
~Test() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct Holder {
Holder(const Test& t):m_t(t) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
~Holder() {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
const Test& m_t;
};
int main() {
Holder(Test());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,我很惊讶地看到编译器实际上已经优化了整个事情,就像在codebolt上看到的那样
但是,如果我真的给临时的名字,通过改变线
Holder(Test());
Run Code Online (Sandbox Code Playgroud)
成
Holder h((Test()));
Run Code Online (Sandbox Code Playgroud)
然后它"神奇地"起作用:codebolt.
情节扭曲:如果我切换到c ++ 11并使用类的支撑列表初始化Holder,那么无论我是否为临时名称赋予构造函数,都不会省略构造函数.见codebolt一次.
那么这里有什么问题?我的印象是,带有副作用的构造函数永远不会被省略,但我显然错过了版本之间变化的标准的重要部分. …
我试图更好地理解如何将左值和右值作为引用处理,因此我创建了这个玩具示例:
\n#include <iostream>\n\nstruct Val\n{\n Val(int num) : num(num){};\n ~Val()\n {\n std::cout << "Destructing with value " << num << std::endl;\n }\n\n int num;\n};\n\nconst Val &test(const Val &val)\n{\n return val;\n}\nint main()\n{\n std::cout<< "Creating foo with value 5" <<std::endl;\n const Val &foo = test(Val(5));\n std::cout<< "Creating bar with value 3" <<std::endl;\n const Val &bar(3);\n std::cout<< "Finishing main function" <<std::endl;\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n这打印出:
\nCreating foo with value 5\nDestructing with value 5\nCreating bar with value 3\nFinishing main function\nDestructing with value 3\n …Run Code Online (Sandbox Code Playgroud) 我用 gcc 和 clang-O1和-std=c++20标志编译了以下代码,它似乎按预期工作。
#include <iostream>
struct S { int i; };
template<typename T>
T *get_address(T&& t) { return &t; }
void print_value_from_temporary(S *const s) {
std::cout << s->i << '\n';
s->i = 0;
std::cout << s->i << '\n';
}
int main() {
print_value_from_temporary(get_address(S{42}));
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:这s->i = 0;条线是未定义的行为吗?