给出以下代码:
#include <iostream>
struct implicit_t
{
implicit_t(int x) :
x_m(x)
{
std::cout << "ctor" << std::endl;
}
~implicit_t()
{
std::cout << "dtor" << std::endl;
}
int x_m;
};
std::ostream& operator<<(std::ostream& s, const implicit_t& x)
{
return s << x.x_m;
}
const implicit_t& f(const implicit_t& x)
{
return x;
}
int main()
{
std::cout << f(42) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到以下输出:
ctor
42
dtor
Run Code Online (Sandbox Code Playgroud)
虽然我知道这是正确的,但我不确定为什么.有没有stdc ++知识的人可以向我解释一下?
struct Test
{
Test()
{}
Test(const Test& other)
{
cout << "Copy" << endl;
}
Test(Test&& other)
{
cout << "Move" << endl;
}
};
Test* f()
{
static Test t;
return &t;
}
int main()
{
auto t = *f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是:复制
*f()显然是一个匿名临时对象,因此它应该是一个r值,并且应该调用move-constructor.为什么编译器将其*f()视为l值?
这是编译器的错误,还是我的理解错了?
所以,代码第一:
#include <iostream>
#include <utility>
struct X{
int i;
void transform(){}
X() :i(0){std::cout<<"default\n";}
X(const X& src): i(src.i){std::cout<<"copy\n";}
X(X&& msrc) :i(msrc.i){msrc.i=0;std::cout<<"move\n";}
};
X getTransform(const X& src){
X tx(src);
tx.transform();
return tx;
}
int main(){
X x1;// default
X x2(x1); // copy
X x3{std::move(X{})}; // default then move
X x41(getTransform(x2)); // copy in function ,then what?
X x42(std::move(getTransform(x2))); // copy in funciton, then move
X x51( (X()) );//default, then move? or copy?
// extra() for the most vexing problem
X x52(std::move(X())); //default …Run Code Online (Sandbox Code Playgroud) 我需要一些关于 const 引用的澄清。从这个链接:
const Foo &myFoo = FuncBar();
Run Code Online (Sandbox Code Playgroud)
const 引用延长了本地对象的寿命。但是当我检查这个链接时,尽管他们使用了 const 引用
Sandbox(const string& n) : member(n) {}
Run Code Online (Sandbox Code Playgroud)
字符串“四”的寿命没有增加。
Sandbox sandbox(string("four"));
Run Code Online (Sandbox Code Playgroud)
他们用了这句话
只有本地常量引用才能延长寿命。
那么在第二个链接中,字符串“four”不是主函数的本地字符串吗?const 引用不应该n延长其寿命吗?
那么为什么第二个环节的寿命没有延长呢?
c++ pass-by-reference lifetime temporary-objects reference-binding
这主要是关于与固定大小的数组相关的C++语法的一个问题.
假设我有一个利用类型信息的函数,例如:
template<class T> void fun(T const& t){
std::cout << typeid(t).name() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我可以传递一个值或一个临时对象:
int i;
fun(i); // prints "int" ("i" actually)
fun(int{}); // prints "int" ("i" actually)
Run Code Online (Sandbox Code Playgroud)
但是我不能对数组做同样的事情
double a[10][10];
fun(a); // ok, prints "a[10][10]" ("A10_A10_d" actually)
fun(double[10][10]); // doesn't compile
fun(double{}[10][10]); // doesn't compile
fun(double[10][10]{}); // doesn't compile
fun(double()[10][10]); // doesn't compile
fun(double[10][10]()); // doesn't compile
fun(double(&)[10][10]); // doesn't compile
fun(double(*)[10][10]); // doesn't compile
Run Code Online (Sandbox Code Playgroud)
我原则上可以这样做:
typedef double a1010[10][10];
fun(a1010{});
Run Code Online (Sandbox Code Playgroud)
但是,有没有预先定义一个typedef呢?
是否有可能将一个固定大小的数组作为函数参数就地构造?
完整代码:
template<class T> void fun(T …Run Code Online (Sandbox Code Playgroud) 我不太明白为什么func下面代码中的第二次调用不起作用:
#include <string>\n#include <iostream>\n#include <tuple>\n\nusing Tuple = std::tuple<const int&, const std::string&>;\n\nvoid func(const Tuple& t)\n{\n std::cout << std::get<1u>(t) << std::endl;\n}\n\nint main()\n{\n const int n = 3;\n const std::string text = "xyz";\n \n func(Tuple(n, text));\n\n //Does not work:\n //func(Tuple(5, "abc"));\n\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n临时字符串什么时候"abc"销毁?
编辑1
\n所以,最后,根据 \xe5\xba\xb7\xe6\xa1\x93\xe7\x91\x8b 这是有效的:
\n func(Tuple(5, std::string("abc")));\nRun Code Online (Sandbox Code Playgroud)\n但这并没有:
\n Tuple t(5, std::string("abc"));\n func(t);\nRun Code Online (Sandbox Code Playgroud)\n正确的?如果是的话有什么区别?
\n来自注释3https://eel.is/c++draft/dcl.fct.def.coroutine#13中的
\n\n\n[注3:\xe2\x80\x82如果协程具有通过引用传递的参数,则在该参数引用的实体的生命周期结束后恢复协程可能会导致未定义的行为。\xe2\x80\x94 尾注]
\n
很明显,如果粗心的调用者不能确保提供的参数比协程对象寿命更长,那么在协程中通过引用获取参数可能会导致未定义的行为。
\n但是用临时变量初始化的 const 引用参数又如何呢?如果标准保证参数的生命周期由本地引用延长,这对我来说是有意义的,但我找不到任何相关信息。
\n这是定义的行为吗(假设 coro() 在第一次暂停后使用 obj ),如果是,它是什么?
\ntask<void> coro(const Obj& obj);\n\n...\n\nauto tsk = coro(Obj{});\nco_await tsk;\nRun Code Online (Sandbox Code Playgroud)\n在我看来,如果不允许这样做,则 const 引用根本不能用作协程参数,因为有人传递临时值并假设普通函数行为的风险。
\n在这里查看此代码:
class test
{
int n;
int *j;
public:
test(int m)
{
n = 12;
j = new int;
cin >> *j;
}
void show()
{
cout << n << ' ' << *j << endl;
}
~test()
{
delete j;
}
};
int main()
{
test var = 123;
var.show();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这个程序中,编译器应该抱怨双重删除j.首次删除是在temporary(123)销毁临时对象时完成的.第二次删除是在var销毁对象时完成的.但这工作正常吗?
这是否意味着临时对象不会调用析构函数?
编辑:感谢所有指出问题的人,并在Stack Overflow上进行了讨论.我自己投了最后一次投票.
一个相关的问题:在没有CPP参考ostringstream或ostringstream::str说明其暂时的.这么多人怎么知道的?或者我应该咨询不同的文件?
我有很多与在Debian 7.3(x64)的内存错误麻烦GCC 4.7.2,-std=c++11和std::ostringstream.它导致bizaare结果,如/sf/ask/1488257081/.
完整的程序使用Sqlite.从命令行运行简化案例与Valgrind打印2个不同的错误.整个简化案例程序可以在Code Viewer中找到(我认为在这里发布整个示例有点长).它所做的只是初始化Sqlite,打开数据库,创建表,关闭数据库,以及将数据库统一化.如果发生错误,它会报告错误.没有其他事情发生.
这是简化案例程序的一部分,它只是试图创建一个表.如果表存在,它应该产生错误(它会):
ostringstream qs;
qs.str().reserve(96);
qs << "CREATE TABLE test";
qs << "(";
qs << " userid INTEGER PRIMARY KEY AUTOINCREMENT,";
qs << " username TEXT,";
qs << " salt BLOB,";
qs << " hmac BLOB";
qs << ");";
const char* stmt = qs.str().c_str();
AC_ASSERT(NULL != stmt);
rc = sqlite3_exec(db, stmt, NULL, NULL, &err);
AC_ASSERT(rc == SQLITE_OK);
if(rc != SQLITE_OK) …Run Code Online (Sandbox Code Playgroud) 我写了一个简单的程序来了解更多关于在C++中创建和销毁对象的顺序(使用Visual Studio 2015).这里是:
#include <iostream>
#include <string>
using namespace std;
class A
{
public:
A(string name)
: name(name)
{
cout << "A(" << name << ")::constructor()" << endl;
}
~A()
{
cout << "A(" << name << ")::destructor()" << endl;
}
private:
string name;
};
class C
{
public:
C(string name, A a)
: name(name), a(a)
{
cout << "C(" << name << ")::constructor()" << endl;
}
~C()
{
cout << "C(" << name << ")::destructor()" << endl;
}
private: …Run Code Online (Sandbox Code Playgroud) c++ object-construction temporary-objects object-destruction
c++ ×10
c++11 ×3
c++20 ×2
arrays ×1
constructor ×1
destructor ×1
lifetime ×1
memory-leaks ×1
rvalue ×1
stringstream ×1