过去几年我一直用C++编写代码.但有一个问题我无法弄清楚.我想问一下,C++,rvalues都是临时工吗?
如果不是,任何人都可以提供一个例子,其中代码中的临时生成是左值?
对于这个计划
#include <iostream>
using std::cout;
struct C
{
C() { cout << "Default C called!\n"; }
C(const C &rhs) { cout << "CC called!\n"; }
};
const C f()
{
cout << "Entered f()!\n";
return C();
}
int main()
{
C a = f();
C b = a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是:
Entered f()!
Default C called!
CC called!
Run Code Online (Sandbox Code Playgroud)
由于f()
按值返回,它应该返回一个临时值.由于T a = x;
是T a(x);
,是不是要求建设的拷贝构造函数a
,使用临时传入作为它的参数?
c++ variable-assignment copy-constructor compiler-optimization temporaries
C++ 03中的第12.2.5节说" 在构造函数的ctor-initializer(12.6.2)中绑定到引用成员的临时绑定一直存在,直到构造函数退出 "
所以我尝试了以下程序
#include<iostream>
using namespace std;
struct foo
{
foo()
{
cout<<"foo c'tor"<<endl;
}
~foo()
{
cout<<"foo d'tor"<<endl;
}
};
struct bar
{
const foo &ref;
bar():ref(foo())
{
cout<<"bar c'tor"<<endl;
}
};
int main()
{
bar obj;
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是:
foo c'tor
foo d'tor
bar c'tor
Run Code Online (Sandbox Code Playgroud)
现在根据标准,在条形码c'tor的c'tor init-list中由foo()生成的临时性将在bar'c'tor之后被销毁,所以foo d'tor
应该在之后打印,bar c'tor
但它是相反的.
请解释原因.
我被告知,在C++ 03中,临时性是隐含的不可修改的.
但是,以下为GCC 4.3.4编译(在C++ 03模式下):
cout << static_cast<stringstream&>(stringstream() << 3).str();
Run Code Online (Sandbox Code Playgroud)
这是怎么编译的?
(我不是在谈论有关临时引用的临时规则.)
请考虑以下代码:
void ListenerImpl::attach(boost::shared_ptr<ISubscriber> subscriber)
{
boost::unique_lock<boost::mutex>(mtx);
subscribers.push_back(subscriber);
}
void ListenerImpl::notify(MsgPtr msg)
{
boost::unique_lock<boost::mutex>(mtx);
//notify all subscribers
BOOST_FOREACH(boost::shared_ptr<ISubscriber> subscriber, subscribers){
subscriber->update(msg);
}
}
Run Code Online (Sandbox Code Playgroud)
(这是GoF中描述的观察者模式的实现.)这里的用户干预是保护attach()和notify()不同时运行,因此boost :: unique_lock.目标是保护subscribers
容器.
但确实很难注意到锁实际上只是暂时的(仔细看,没有为它们指定名称).因此,当临时被破坏时,互斥锁上的锁定将被立即释放,即代码不是线程安全的.我希望在这种情况下编译器警告.像"未使用的临时"之类的东西.
更糟糕的是,cppcheck也不会认识到这个错误.(cppcheck:ac/c ++代码分析工具http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page)
Gcc对未使用的变量发出警告.这里的临时变量是一个未使用的变量,绝对是程序员注意力不集中的结果.那么,为什么在这种情况下没有警告呢?发现这种情况可能太复杂了吗?
这可能是不可能的,但我想知道是否有可能暂时不会超过其原始表达.我有一个指向父对象的对象链,以及一个将创建子对象的成员函数,这里有一个简化的例子
class person{
string name;
person * mommy;
public:
person(const string & nam, person * m = 0) : name(nam), mommy(m) {}
person baby(const string & nam){
return person(nam, this);
}
void talk() const{
if (mommy) mommy->talk();
cout << name << endl;
}
};
int main(){
person("Ann").baby("Susan").baby("Wendy").talk(); // fine
const person & babygirl = person("Julie").baby("Laura"); // not fine
babygirl.talk(); // segfault
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想要使用的方法person
是将它传递给一个函数,如下所示:
void use(const person & p) {
p.talk();
}
use(person("Anna").baby("Lisa"));
Run Code Online (Sandbox Code Playgroud)
很好.
只要没有一个临时表现在原始表达式之后,这就可以正常工作,但是如果我把一个最后的临时工具绑定到一个const引用,那么它的父母就无法生存,我得到一个段错误.我可以隐藏person
复制构造函数和赋值运算符,但有什么方法可以防止这种错误发生?如果可能的话,我想避免动态分配.
我正在做类似这个项目正确的BOOST_FOREACH用法吗?
但是,我返回的列表包含在boost :: shared_ptr中.如果我没有在BOOST_FOREACH循环之前将列表分配给变量,那么我会在运行时遇到崩溃,因为列表正在被破坏,因为它是临时的.
boost::shared_ptr< list<int> > GetList()
{
boost::shared_ptr< list<int> > myList( new list<int>() );
myList->push_back( 3 );
myList->push_back( 4 );
return myList;
}
Run Code Online (Sandbox Code Playgroud)
然后......
// Works if I comment out the next line and iterate over myList instead
// boost::shared_ptr< list<int> > myList = GetList();
BOOST_FOREACH( int i, *GetList() ) // Otherwise crashes here
{
cout << i << endl;
}
Run Code Online (Sandbox Code Playgroud)
我希望能够使用上面的内容而不必引入变量'myList'.这可能吗?
我编写了以下代码来测试这个:
struct X
{
char* x;
X()
{
x = new char('a');
}
~X()
{
*x = 'b';
delete x;
}
};
void foo(const X& x)
{
}
void goo(X& x)
{
}
int main()
{
foo(X());
goo(X());
}
Run Code Online (Sandbox Code Playgroud)
两个函数退出后调用临时函数的析构函数,但我认为你只能将临时函数绑定到const
引用.为什么goo
工作呢?
是UB和MSVS是错的,还是没问题?
考虑以下代码:
class cFoo {
private:
int m1;
char m2;
public:
int doSomething1();
int doSomething2();
int doSomething3();
}
class cBar {
private:
cFoo mFoo;
public:
cFoo getFoo(){ return mFoo; }
}
void some_function_in_the_callstack_hierarchy(cBar aBar) {
int test1 = aBar.getFoo().doSomething1();
int test2 = aBar.getFoo().doSomething2();
...
}
Run Code Online (Sandbox Code Playgroud)
在调用getFoo()的行中,编译器将生成cFoo的临时对象,以便能够调用doSomething1().编译器是否重用用于这些临时对象的堆栈内存?"some_function_in_the_callstack_hierarchy"的调用将保留多少堆栈内存?是否为每个生成的临时存储内存?
我的猜测是编译器只为cFoo的一个对象保留内存,并将重用内存用于不同的调用,但如果我添加
int test3 = aBar.getFoo().doSomething3();
Run Code Online (Sandbox Code Playgroud)
我可以看到"some_function_in_the_callstack_hierarchy"所需的堆栈大小更多,而且不仅仅是因为附加的本地int变量.
另一方面,如果我然后更换
cFoo getFoo(){ return mFoo; }
Run Code Online (Sandbox Code Playgroud)
带引用(仅用于测试目的,因为返回对私有成员的引用不好)
const cFoo& getFoo(){ return mFoo; }
Run Code Online (Sandbox Code Playgroud)
它需要的堆栈内存少于一个cFoo的大小.
所以对我来说,似乎编译器为函数中的每个生成的临时对象保留了额外的堆栈内存.但这样效率很低.有人可以解释一下吗?
具体来说,我想知道我应该写些:
{
shared_ptr<GuiContextMenu> subMenu = items[j].subMenu.lock();
if (subMenu)
subMenu->setVisible(false);
}
Run Code Online (Sandbox Code Playgroud)
要么:
{
if (items[j].subMenu.lock())
items[j].subMenu.lock()->setVisible(false);
}
Run Code Online (Sandbox Code Playgroud)
我不需要遵循任何风格指南.优化后,我认为这两种选择都不会对性能产生影响.什么是一般的首选风格,为什么?
编辑:项目类型[j] .subMenu是boost :: weak_ptr.lock()从中创建一个shared_ptr.上面两个版本实际上有一个模糊的区别,关于临时shared_ptr持续多长时间,所以我将我的两个例子包装在{braces}中以解决那里的歧义.
我有一个对字符串进行转换的类,如下所示
class transer{
transer * parent;
protected:
virtual string inner(const string & s) = 0;
public:
string trans(const string & s) {
if (parent)
return parent->trans(inner(s));
else
return inner(s);
}
transer(transer * p) : parent(p) {}
template <class T>
T create() { return T(this); }
template <class T, class A1> // no variadic templates for me
T create(A1 && a1) { return T(this, std::forward(a1)); }
};
Run Code Online (Sandbox Code Playgroud)
所以我可以创建一个子类
class add_count : public transer{
int count;
add_count& operator=(const add_count &);
protected:
virtual …
Run Code Online (Sandbox Code Playgroud) 有人可以解释为什么这不起作用的原因:
std::shared_pointer<Bar> getSharedPointer() {
return std::make_shared<Bar>();
}
...
auto foo = getSharedPointer().get();
Run Code Online (Sandbox Code Playgroud)
显然使用原始指针foo
会导致段错误,因为返回的共享指针的生命周期getSharedPointer()
将耗尽.不知怎的,我希望它能持续到它的范围结束(就像它里面的任何块一样).
这是正确的,这种情况有什么类似的例子吗?
如果我有一个列表理解
[mymap.get(x, None) for x in oldlist if mymap.get(x,None)]
Run Code Online (Sandbox Code Playgroud)
有没有办法mymap.get(x,None)
只在这里做一次?
我想像
[y for x in oldlist if mymap.get(x,None) as y]
Run Code Online (Sandbox Code Playgroud)
但是目前这是SyntaxError
py 2.x中的。我希望能够引用列表理解的“表达式”或它的“ list_if”部分的结果值。
我也尝试过
[_ for x in oldlist if mymap.get(x,None)]
Run Code Online (Sandbox Code Playgroud)
但这是一个NameError
,我想_
只是在线上的某些解释器功能。
编辑
有没有办法以某种方式引用此临时/匿名/未命名变量,而无需重新列出该列表?
temporaries ×13
c++ ×12
boost ×1
gcc-warning ×1
lifetime ×1
pointers ×1
python ×1
reference ×1
rvalue ×1
shared-ptr ×1
stack ×1
styles ×1
templates ×1
temporary ×1